hdu 1565 方格取數(1)(最小割)
阿新 • • 發佈:2019-02-10
方格取數(1)
Problem Description 給你一個n*n的格子的棋盤,每個格子裡面有一個非負數。從中取出若干個數,使得任意的兩個數所在的格子沒有公共邊,就是說所取的數所在的2個格子不能相鄰,並且取出的數的和最大。
Input 包括多個測試例項,每個測試例項包括一個整數n 和n*n個非負數(n<=20)
Output 對於每個測試例項,輸出可能取得的最大的和
Sample Input 3 75 15 21 75 15 28 34 70 5
Sample Output 188
Author ailyanlu
Source Happy 2007 設定源點與匯點s,t 源點與白點連邊,容量為白點上的數 黑點與匯點連邊,容量為黑點上的數 白點與他周圍的黑點連邊,容量為inf 這樣我們只要求這個圖的最小割,使得源點與匯點不想連,然後剩下的數字即為所求 定理 最小割=最大流
#include <iostream> #include <cstdio> #include <cstring> #include<queue> #define maxn 555 #define inf 9999999 using namespace std; int map[maxn][maxn],tag[maxn],pre[maxn],f[maxn]; int a[maxn][maxn]; int n,s,t,ans,tot,N=99; int q[maxn],bot,top; void init() { s=0,t=n*n+1,ans=tot=0; memset(map,0,sizeof(map)); } void graph() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if((i+j)%2==1) { int cur=i*n+j-n; map[s][cur]+=a[i][j]; if (i>1) map[cur][cur-n]=inf; if (i<n) map[cur][cur+n]=inf; if (j>1) map[cur][cur-1]=inf; if (j<n) map[cur][cur+1]=inf; } else map[i*n+j-n][t]+=a[i][j]; } void bfs() { int u,v; queue<int>q; while(1) { memset(f,0,sizeof(f)); f[s]=inf; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) { u=q.front(); q.pop(); for(v=s;v<=t;v++) { if(!f[v]&&map[u][v]>0) { pre[v]=u; q.push(v); f[v]=min(f[u],map[u][v]); } } if(f[t]) break; } if(f[t]==0) break; ans+=f[t]; for(int i=t;i!=s;i=pre[i]) { map[pre[i]][i]-=f[t]; map[i][pre[i]]+=f[t]; } } } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]),tot+=a[i][j]; graph(); bfs(); printf("%d\n",tot-ans); } return 0; }