HDU 3820 Golden Eggs

http://acm.hdu.edu.cn/showproblem.php?pid=3820

题意:
n*m的格子,每个格子放金蛋或银蛋,每个格子的金蛋和银蛋都有一个对应的点权,如果有两个金蛋相连,则需要G的代价,如果有两个银蛋相连,需要S的代价。

思路:

这道题和HDU的格子取数是一个套路。

在前面的格子取数问题中,我们奇偶建图,相邻点之间连INF就代表这两个点中至少会选择一个,由于是最小割,肯定是选择权值小的点。这道题目的建图稍微复杂点,因为每个格子有三种选择,即可以选择放金蛋或是放银蛋或空着。首先,我们还是要奇偶建图,把一方的金蛋与源点相连,银蛋与汇点相连,而另一方的金蛋与汇点相连,银蛋与源点相连。每一方的金蛋与自己的银蛋相连,容量为INF,说明要么放金蛋,要么放银蛋。而相邻的蛋颜色相同时则边的容量为代价。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue>
  7 using namespace std;
  8
  9 const int maxn = 1e5 + 5;
 10 const int INF=0x3f3f3f3f;
 11
 12 struct Edge
 13 {
 14     int from,to,cap,flow;
 15     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
 16 };
 17
 18 struct Dinic
 19 {
 20     int n,m,s,t;
 21     vector<Edge> edges;
 22     vector<int> G[maxn];
 23     bool vis[maxn];
 24     int cur[maxn];
 25     int d[maxn];
 26
 27     void init(int n)
 28     {
 29         this->n=n;
 30         for(int i=0;i<n;++i) G[i].clear();
 31         edges.clear();
 32     }
 33
 34     void AddEdge(int from,int to,int cap)
 35     {
 36         edges.push_back( Edge(from,to,cap,0) );
 37         edges.push_back( Edge(to,from,0,0) );
 38         m=edges.size();
 39         G[from].push_back(m-2);
 40         G[to].push_back(m-1);
 41     }
 42
 43     bool BFS()
 44     {
 45         queue<int> Q;
 46         memset(vis,0,sizeof(vis));
 47         vis[s]=true;
 48         d[s]=0;
 49         Q.push(s);
 50         while(!Q.empty())
 51         {
 52             int x=Q.front(); Q.pop();
 53             for(int i=0;i<G[x].size();++i)
 54             {
 55                 Edge& e=edges[G[x][i]];
 56                 if(!vis[e.to] && e.cap>e.flow)
 57                 {
 58                     vis[e.to]=true;
 59                     d[e.to]=d[x]+1;
 60                     Q.push(e.to);
 61                 }
 62             }
 63         }
 64         return vis[t];
 65     }
 66
 67     int DFS(int x,int a)
 68     {
 69         if(x==t || a==0) return a;
 70         int flow=0, f;
 71         for(int &i=cur[x];i<G[x].size();++i)
 72         {
 73             Edge &e=edges[G[x][i]];
 74             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
 75             {
 76                 e.flow +=f;
 77                 edges[G[x][i]^1].flow -=f;
 78                 flow +=f;
 79                 a -=f;
 80                 if(a==0) break;
 81             }
 82         }
 83         return flow;
 84     }
 85
 86     int Maxflow(int s,int t)
 87     {
 88         this->s=s; this->t=t;
 89         int flow=0;
 90         while(BFS())
 91         {
 92             memset(cur,0,sizeof(cur));
 93             flow +=DFS(s,INF);
 94         }
 95         return flow;
 96     }
 97 }DC;
 98
 99 int n,m;
100 int G,S;
101 int map[105][55];
102 int dx[]={0,0,1,-1};
103 int dy[]={1,-1,0,0};
104
105 int main()
106 {
107     //freopen("D:\\input.txt","r",stdin);
108     int kase=0;
109     int T;
110     scanf("%d",&T);
111     while(T--)
112     {
113         int sum=0;
114         scanf("%d%d%d%d",&n,&m,&G,&S);
115         int src=0,dst=2*n*m+1;
116         DC.init(dst+1);
117         for(int i=1;i<=n;i++)
118         for(int j=1;j<=m;j++)
119         {
120             scanf("%d",&map[i][j]);
121             sum+=map[i][j];
122         }
123         for(int i=1;i<=n;i++)
124         for(int j=1;j<=m;j++)
125         {
126             scanf("%d",&map[i+n][j]);
127             sum+=map[i+n][j];
128         }
129         for(int i=1;i<=n;i++)
130         for(int j=1;j<=m;j++)
131         {
132             int id1=(i-1)*m+j;
133             int id2=(i+n-1)*m+j;
134             int t=(i+j)%2;
135             //0为金色
136             if(t==0)
137             {
138                 DC.AddEdge(src,id1,map[i][j]);    //金
139                 DC.AddEdge(id2,dst,map[i+n][j]);  //银
140                 DC.AddEdge(id1,id2,INF);
141                 for(int k=0;k<4;k++)
142                 {
143                     int x=i+dx[k];
144                     int y=j+dy[k];
145                     if(x<1||x>n||y<1||y>m)  continue;
146                     DC.AddEdge(id1,(x+n-1)*m+y,G);
147                 }
148             }
149             else
150             {
151                 DC.AddEdge(src,id1,map[i+n][j]);
152                 DC.AddEdge(id2,dst,map[i][j]);
153                 DC.AddEdge(id1,id2,INF);
154                 for(int k=0;k<4;k++)
155                 {
156                     int x=i+dx[k];
157                     int y=j+dy[k];
158                     if(x<1||x>n||y<1||y>m)  continue;
159                     DC.AddEdge(id1,(x+n-1)*m+y,S);
160                 }
161             }
162         }
163
164         int ans=sum-DC.Maxflow(src,dst);
165         printf("Case %d: %d\n",++kase,ans);
166     }
167     return 0;
168 }
时间: 2024-10-12 22:30:56

HDU 3820 Golden Eggs的相关文章

hdoj 3820 Golden Eggs 【最小割+拆点】

题目:hdoj 3820 Golden Eggs 题意:给出一个矩阵,然后当前有三种选择,放一个金蛋,放一个银蛋,或者不放,然后给出每个格子放金蛋或者银蛋的得分,如果金蛋相邻的话每个得分要减掉cost1,银蛋相邻的话每个减去cost2得分,问最大得分多少? 分析:做这个题目推荐先做hdoj 1659 ,3657点击打开链接 ,这个题目相当于前两个的融合在加点变化. 首先我们发现和前两个题目一样要求不能相邻,否则要减去一定的值,那么我们可以确定同样要用当前点的行列和的奇偶性建图. 那么我们可以按照

hdoj 3820 Golden Eggs 【双二分图构造最小割模型】

Golden Eggs Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 505    Accepted Submission(s): 284 Problem Description There is a grid with N rows and M columns. In each cell you can choose to put

Golden Eggs HDU - 3820(最小割)

Golden Eggs Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 673    Accepted Submission(s): 400 Problem Description There is a grid with N rows and M columns. In each cell you can choose to put a

HDU - 4814 Golden Radio Base (长春赛区B题)

最小二乘法又叫做最小平方法,是一种数学优化技术.它通过最小化误差的平方和寻找数据的最佳函数匹配. 通常情况下最小二乘法用于求回归问题.以简单的线性最小二乘为例,二维平面上给定个点的坐标,确定一条直线, 要求大致符合这个点的走向. 我们可以设这条直线的方程为,那么就要使在处的函数值与给定的值相 差达到最小,也就是说,要确定的值,使得 最小.根据这种方法求的值就是典型的最小二乘法. 可以看出是的一个二元函数,要求的最小值,那么求偏导,有 进一步得到 然后联立两式可以解出,如果方程数比较多,我们可以用

HDU 4814 Golden Radio Base 小模拟

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4814 题意:黄金比例切割点是,如今要求把一个10进制的的数转化成一个phi进制的数,而且不能出现'11'的情况. 思路:因为题目中给出了两个式子,题目就变成了一道简单的模拟题了.因为整个phi进制的数最多仅仅有200,而数据中最多仅仅有100位,所以从aa[50]=tot 開始模拟就可以. 代码: #include<iostream> #include<cstdio> #include&l

HDU 4814 Golden Radio Base 模拟

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4814 题目大意: 把一个正整数表示为φ进制, φ = (1+√5)/2 . 且已知: 1. φ + 1 = φ 2 ,所以有11(φ) = 100(φ),且要求11要转变为100 2. 2 * φ 2  = φ3 + 1 . 解题思路: 观察发现,2 = 10.01.所以对于一个数N,能够从N/2 推导得到,是一个模拟的过程.我比赛的时候居然用了高速幂... 代码: #include<cstdio>

HDU3820 Golden Eggs(最小割)

题目大概说给一个n*m的格子,每个格子放金蛋或银蛋都会得到不同的价值,当然也可以不放,不过如果存在相邻的两个格子都是金蛋会损失价值g,都是银则损失s.问能得到的最大价值. 有点像二者选一的最小割模型,所以应该能想到用最小割求解,最小割的目的就是最小化损失的价值,包括不放金蛋或不放银蛋以及相邻相同蛋的损失的价值: 对格子黑白染色形成x和y两部分的点,并拆成两点x.x'和y.y' 源点向x连容量为该格子放金蛋的价值的边,x'向汇点连容量为该格子放银蛋的价值的边 源点向y连容量为该格子放银蛋的价值的边

HDU 5815 - Golden Week

题意: 王国地图为 n 个节点的根树,首都为 1, m 个旅行家要去不同的终点旅游,他们分别有各自的预算,如果路上总费用超过预算就不去了 给每条路定价, 让赚的钱最多 分析:    DP[i][j]表示当从首都到城市i的路径花费为j时,以i为根的子树中的点作为目的城市的旅行者的最大花费. 只需要考虑j值等于0或等于某位旅行者预算的情况,所以dp的状态数是O(NM)的. 状态转移方程式: DP[i][j] = j* n(i,j) + ∑?max(DP[k][j?i]) (ji >= j) ( n(

HDU 4814 Golden Radio Base

很显然是个进制转换的题,根据题意有a^2 = a + 1  -> a^n = a^(n-1) + a^(n-2),这样就能消除两个连续1. 另,a^3 = a^2 + 1 = 2*a+2 = 2*(a+1)  =  2*a.这样就可以将悉数转化为01. 10^9大约是2^30,所以总长度不超高150,直接模拟就好了. #include <algorithm> #include <iostream> #include <cstring> #include <c