網路流24題09方格取數問題
網路流24題09方格取數問題
題目描述
在一個有 m*n 個方格的棋盤中,每個方格中有一個正整數。現要從方格中取數,使任意 2 個數所在方格沒有公共邊,且取出的數的總和最大。試設計一個滿足要求的取數演算法。對於給定的方格棋盤,按照取數要求程式設計找出總和最大的數。
輸入
第 1 行有 2 個正整數 m 和 n,分別表示棋盤的行數和列數。接下來的 m 行,每行有 n 個正整數,表示棋盤方格中的數。
輸出
程式執行結束時,將取數的最大總和輸出
Solution
考慮網路流。
把每個可以同時選的兩個點建邊,最後要使流量最大
可是
n<=100
,邊的數量就會爆炸 不如換種方式考慮。
假設先把全部的選上,然後把不滿足的刪掉,要使刪掉的數量儘可能小。
這樣就有了一種最小割的感覺。
將所有點按照所在行和列之和的奇偶性分成兩部分(因為與一個點相鄰的點奇偶性不同,就形成了一張二分圖)
建圖:
1. 將S與每個奇點相連,權值為這個點的價值(意思是將這個點刪除要花費w的代價)
2. 同理將每個偶點與T相連,權值為這個點的價值
3. 從每個奇點向相鄰的每個偶點連一條權值為inf的邊,說明這兩個點必然至少有一個會被刪掉。
然後跑一邊最小割。
因為最小割求的是要使刪的數目最小,所以答案是總和-最小割。
洛谷上可以測
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 1000010
const int inf=1e9+7;
inline int read(){
int ret=0,ff=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') ff=-ff;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
ret=ret*10+ch-'0';
ch=getchar();
}
return ret*ff;
}
int n,m,s,t;
struct Edge{
int u,v,w,next;
}E[maxn];
int ecnt=1;
int head[maxn],dis[maxn];
void addedge(int u,int v,int w){
E[++ecnt].u=u;
E[ecnt].v=v;
E[ecnt].w=w;
E[ecnt].next=head[u];
head[u]=ecnt;
}
void Addedge(int u,int v,int w){
addedge(u,v,w);
addedge(v,u,0);
}
int dfs(int x,int nar){
if(x==t) return nar;
int used=0;
for(int i=head[x];i;i=E[i].next){
int v=E[i].v;
if(dis[v]!=dis[x]+1||!E[i].w) continue;
int tmp=nar-used;
int flow=dfs(v,min(tmp,E[i].w));
used+=flow;
E[i].w-=flow;
E[i^1].w+=flow;
if(used==nar) return nar;
}
if(!used) dis[x]=-1;
return used;
}
bool bfs(){
queue<int> q;
for(int i=1;i<=t;++i) dis[i]=inf;
dis[s]=1;
q.push(s);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=E[i].next){
int v=E[i].v;
if(dis[v]<inf||!E[i].w) continue;
q.push(v);
dis[v]=dis[x]+1;
}
}
return dis[t]!=inf;
}
int Dinic(){
int ans=0;
while(bfs()){
ans+=dfs(s,inf);
}
return ans;
}
int main(){
n=read(),m=read();
s=n*m+1,t=s+1;
int sum=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int c=read();
sum+=c;
int p=(i-1)*m+j;
if((i+j)&1){
Addedge(s,p,c);
if(i>1) Addedge(p,p-m,inf);
if(i<n) Addedge(p,p+m,inf);
if(j>1) Addedge(p,p-1,inf);
if(j<m) Addedge(p,p+1,inf);
}
else Addedge(p,t,c);
}
}
printf("%d\n",sum-Dinic());
return 0;
}
相關文章
- [網路流24題] 魔術球問題 (最大流)
- 做題筆記——網路流與線性規劃24題筆記
- 網路瘤 24 題做題寄錄
- Python小白的數學建模課-19.網路流優化問題Python優化
- POJ 3279-Fliptile(母牛翻方格-開關問題)
- 面試必考:網路問題面試
- 公司網路有問題
- 第七章 遞迴、DFS、剪枝、回溯等問題 ------------- 7.3 題解:機器人走方格問題遞迴機器人
- 卷積核大小選擇、網路層數問題卷積
- NOIP2000方格取數[DP]
- 奇葩網路問題歸總
- 求資料流中的中位數問題
- 洛谷OJ:P2764 最小路徑覆蓋問題(網路流)
- [codevs 1227] 方格取數 2dev
- hdu5445 || 2015長春網路賽1009題 多重揹包問題
- 04.JavaIO流問題JavaAI
- 【Django】檔案讀取時路徑問題Django
- Windows程式讀取不了中文路徑問題Windows
- 藍橋python—— 方格填數【2016 第六題】Python
- 未來網路若干問題思考
- 網路問題定位工具記錄
- android 網路通知的問題Android
- java nio網路開發問題Java
- socket網路傳輸的問題
- 使用 nsenter 排查容器網路問題
- 從網路鏈路到跨域問題跨域
- MyBatis-09-FactoryBean的問題MyBatisBean
- Java演算法面試題(009) 毒酒問題Java演算法面試題
- 如何排查網路問題-開發眼裡的網路
- 快取的問題快取
- beego快取問題Go快取
- SOAP快取問題快取
- 04_利用手寫數字問題引入深度神經網路神經網路
- 使用MTR命令診斷網路問題
- IOS9後網路的問題iOS
- 重啟系統,網路有問題
- 解決oracle網路連線問題Oracle
- linux網路問題:Network is unreachableLinux