HDU 3820 Golden Eggs
2013-10-30 16:26
288 查看
题意:有一个n*m的矩阵,里面可以放金蛋也可以放银蛋。分别给出在2个矩阵map1,map2表示在矩阵的每个格子里放金蛋的得分和放银蛋的得分。如果相邻的两个格子里都放了金蛋,则总得分要减去G,如果相邻的两个格子里都放了银蛋,则总得分要减去S。现要求你求出放蛋的最大得分。
跟HDU 3657比较像,但是这里更加复杂了,因为两种得分,一种金蛋,一种银蛋。所以我的理解是这里是两个二分图合起来的一个二分图,因为金蛋和银蛋存在一个匹配的关系,给矩阵染色后,黑格和白格也存在一个匹配的关系。因此,这样建图:假设行数i+列数j这和为偶数的格子为黑格,奇数的为白格,每个格子拆成两个点k,k',分别表示放金蛋还是放银蛋,所以图中一共有2*n*m+2个点。
建图的方法大概是这样的:
View Code
跟HDU 3657比较像,但是这里更加复杂了,因为两种得分,一种金蛋,一种银蛋。所以我的理解是这里是两个二分图合起来的一个二分图,因为金蛋和银蛋存在一个匹配的关系,给矩阵染色后,黑格和白格也存在一个匹配的关系。因此,这样建图:假设行数i+列数j这和为偶数的格子为黑格,奇数的为白格,每个格子拆成两个点k,k',分别表示放金蛋还是放银蛋,所以图中一共有2*n*m+2个点。
建图的方法大概是这样的:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define INF 1<<30 #define maxn 5010 #define maxm 100000 using namespace std; int v[maxm],next[maxm],w[maxm]; int first[maxn],d[maxn],work[maxn],q[maxn]; int e,S,T; int n,m,gold,silver; int map1[55][55],map2[55][55]; void init(){ e = 0; memset(first,-1,sizeof(first)); } void add_edge(int a,int b,int c){ //printf("add:%d to %d,cap = %d\n",a,b,c); v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++; v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++; } int bfs(){ int rear = 0; memset(d,-1,sizeof(d)); d[S] = 0;q[rear++] = S; for(int i = 0;i < rear;i++){ for(int j = first[q[i]];j != -1;j = next[j]) if(w[j] && d[v[j]] == -1){ d[v[j]] = d[q[i]] + 1; q[rear++] = v[j]; if(v[j] == T) return 1; } } return 0; } int dfs(int cur,int a){ if(cur == T) return a; for(int &i = work[cur];i != -1;i = next[i]){ if(w[i] && d[v[i]] == d[cur] + 1) if(int t = dfs(v[i],min(a,w[i]))){ w[i] -= t;w[i^1] += t; return t; } } return 0; } int dinic(){ int ans = 0; while(bfs()){ memcpy(work,first,sizeof(first)); while(int t = dfs(S,INF)) ans += t; } return ans; } int main() { int nkase; scanf("%d",&nkase); for(int kase = 1;kase <= nkase;kase++){ scanf("%d%d%d%d",&n,&m,&gold,&silver); S = 0,T = 2*n*m+1; init(); int sum = 0,k = n*m; for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++) scanf("%d",&map1[i][j]),sum += map1[i][j]; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++) scanf("%d",&map2[i][j]),sum += map2[i][j]; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++){ int pos = (i-1)*m+j; if((i+j)%2 == 1){ add_edge(S,pos,map1[i][j]); add_edge(pos+k,T,map2[i][j]); add_edge(pos,pos+k,INF); if(i > 1) add_edge(pos,pos-m,gold); if(i < n) add_edge(pos,pos+m,gold); if(j > 1) add_edge(pos,pos-1,gold); if(j < m) add_edge(pos,pos+1,gold); }else{ add_edge(S,pos+k,map2[i][j]); add_edge(pos,T,map1[i][j]); add_edge(pos+k,pos,INF); if(i > 1) add_edge(pos+k,pos+k-m,silver); if(i < n) add_edge(pos+k,pos+k+m,silver); if(j > 1) add_edge(pos+k,pos+k-1,silver); if(j < m) add_edge(pos+k,pos+k+1,silver); } } } printf("Case %d: %d\n",kase,sum-dinic()); } return 0; }
View Code
相关文章推荐
- HDU 3820 Golden Eggs( 最小割 奇特建图)经典
- HDU 3820 Golden Eggs (最小割)
- HDU3820 Golden Eggs(最小割)
- HDU 3820 Golden Eggs( 最小割 奇特建图)经典
- hdu 3820 Golden Eggs【最大流Dinic-------最小割】好题
- HDU 3820 Golden Eggs 方格取数加强版
- 【HDU】3820 Golden Eggs 最小割
- hdu 3820 Golden Eggs(最小割,最大点权独立集+拆点)
- hdu 3820 Golden Eggs 最小割
- hdu 3820 Golden Eggs 最小割
- hdu 3820 Golden Eggs 最小割
- HDU 3820 Golden Eggs(最大独立集)
- hdu 3820 Golden Eggs(最小割+SAP)
- hdoj 3820 Golden Eggs 【双二分图构造最小割模型】
- hdu 3820
- HDU 3820 Golden Eggs
- HDOJ 3820 - Golden Eggs 构图最小割(类似二分图的最大独立点权集)
- hdoj 3820 Golden Eggs 【最小割+拆点】
- HDU-1298 T9 字典树 DFS
- HDU 1062 Text Reverse(简单模拟)