ACdream 1128 Maze(费用流)
2014-07-22 16:06
369 查看
题目链接:http://acdream.info/problem?pid=1128
每组数据第一行是两个正整数N和M(1<=N,M<=100)。
接下来一行两个整数为x和y(1<=x,y<=100)
接下来N行,每行有M个非负整数,第i行的第j个数为p(i,j)(0<=p(i,j)<=20)代表(i,j)格子上有的箱子数。
题目大意:略。
思路:考虑结果的话,每行的总和是一样的,每列的总和是一样的。那么每行的总和是n的倍数,每列的总和是m的倍数。那么整个棋盘的总和一定是lcm(n, m)的倍数。
那么枚举最终棋盘剩余的箱子数,枚举lcm(n, m)的倍数,假设为b,那么需要销毁的箱子数为(sum - b) * y,其中sum为总箱子数。
现在考虑每一行间箱子的移动,设sumr[i]为第 i 行的箱子总和,现在要求每一行都变成b / n。
建图,建一个源点,连一条边到每一行的容量为sumr[i],费用为0。建一个汇点,每一行到汇点连一条边,容量为b / n,费用为0。
相邻的行之间连一条边,容量为正无穷大,费用为x。
跑最小费用最大流可得到箱子在行之间移动的代价。同理可以得到箱子在列之间移动的代价。
取枚举之后的总代价的最小值。
PS:肉眼DEBUG的时候发现以前一直在用的SPFA费用流模板是错的……
代码(96MS):
View Code
Problem Description
wuyiqi陷入了一个迷宫中,这个迷宫是由N*M个格子组成的矩阵。每个格子上堆放了一定数量的箱子。(i,j)表示第i行,第j列的格子。wuyiqi可以将一个格子上的箱子移动到相邻的格子上,或者在这个格子上销毁。也就是在(i,j)的箱子可以移动到(i-1,j)、(i+1,j)、(i,j-1)和(i,j+1),但是不能移动到矩阵范围外。将(i,j)的格子上的一个箱子移动到相邻格子需要消耗x的RP值,将一个箱子销毁需要消耗y的RP值。当每行的箱子数相等,每列的箱子数相等的时候,wuyiqi就可以逃出去了。求帮wuyiqi算出逃出去需要消耗的最小RP值吧。Input
有多组数据。每组数据第一行是两个正整数N和M(1<=N,M<=100)。
接下来一行两个整数为x和y(1<=x,y<=100)
接下来N行,每行有M个非负整数,第i行的第j个数为p(i,j)(0<=p(i,j)<=20)代表(i,j)格子上有的箱子数。
Output
输出wuyiqi逃离需要消耗的最小RP值。题目大意:略。
思路:考虑结果的话,每行的总和是一样的,每列的总和是一样的。那么每行的总和是n的倍数,每列的总和是m的倍数。那么整个棋盘的总和一定是lcm(n, m)的倍数。
那么枚举最终棋盘剩余的箱子数,枚举lcm(n, m)的倍数,假设为b,那么需要销毁的箱子数为(sum - b) * y,其中sum为总箱子数。
现在考虑每一行间箱子的移动,设sumr[i]为第 i 行的箱子总和,现在要求每一行都变成b / n。
建图,建一个源点,连一条边到每一行的容量为sumr[i],费用为0。建一个汇点,每一行到汇点连一条边,容量为b / n,费用为0。
相邻的行之间连一条边,容量为正无穷大,费用为x。
跑最小费用最大流可得到箱子在行之间移动的代价。同理可以得到箱子在列之间移动的代价。
取枚举之后的总代价的最小值。
PS:肉眼DEBUG的时候发现以前一直在用的SPFA费用流模板是错的……
代码(96MS):
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <queue> #include <numeric> using namespace std; typedef long long LL; const int MAXN = 110; const int MAXV = 110; const int MAXE = 8 * MAXV; const int INF = 0x7f7f7f7f; struct SPFA_COST_FLOW { int head[MAXV]; int to[MAXE], next[MAXE], cost[MAXE], flow[MAXE]; int n, ecnt, st, ed; void init(int nn) { n = nn; memset(head + 1, -1, n * sizeof(int)); ecnt = 0; } void add_edge(int u, int v, int c, int w) { to[ecnt] = v; flow[ecnt] = c; cost[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++; to[ecnt] = u; flow[ecnt] = 0; cost[ecnt] = -w; next[ecnt] = head[v]; head[v] = ecnt++; } bool vis[MAXV]; int dis[MAXV], pre[MAXV]; queue<int> que; bool spfa() { memset(vis + 1, 0, n * sizeof(bool)); memset(dis + 1, 0x7f, n * sizeof(int)); dis[st] = 0; que.push(st); while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = false; for(int p = head[u]; ~p; p = next[p]) { int &v = to[p]; if(flow[p] && dis[v] > dis[u] + cost[p]) { dis[v] = dis[u] + cost[p]; pre[v] = p; if(!vis[v]) { que.push(v); vis[v] = true; } } } } return dis[ed] < INF; } int maxFlow, minCost; int min_cost_flow(int ss, int tt) { st = ss, ed = tt; maxFlow = minCost = 0; while(spfa()) { int u = ed, tmp = INF; while(u != st) { tmp = min(tmp, flow[pre[u]]); u = to[pre[u] ^ 1]; } u = ed; while(u != st) { flow[pre[u]] -= tmp; flow[pre[u] ^ 1] += tmp; u = to[pre[u] ^ 1]; } maxFlow += tmp; minCost += tmp * dis[ed]; } return minCost; } } G; int mat[MAXN][MAXN]; int sumr[MAXN], sumc[MAXN]; int n, m, x, y; int calc(int sum[], int n, int c) { int ss = n + 1, tt = n + 2; G.init(n + 2); for(int i = 1; i <= n; ++i) G.add_edge(ss, i, sum[i], 0), G.add_edge(i, tt, c, 0); for(int i = 1; i < n; ++i) G.add_edge(i, i + 1, INF, x), G.add_edge(i + 1, i, INF, x); return G.min_cost_flow(ss, tt); } int solve() { int sum = accumulate(sumr + 1, sumr + n + 1, 0), ans = sum * y; int lcm = n * m / __gcd(n, m); for(int b = lcm; b <= sum; b += lcm) { ans = min(ans, (sum - b) * y + calc(sumr, n, b / n) + calc(sumc, m, b / m)); } return ans; } int main() { while(scanf("%d%d", &n, &m) != EOF) { scanf("%d%d", &x, &y); for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) scanf("%d", &mat[i][j]); memset(sumr + 1, 0, n * sizeof(int)); memset(sumc + 1, 0, m * sizeof(int)); for(int i = 1; i <= n; ++i) { for(int j = 1; j <= m; ++j) { sumr[i] += mat[i][j]; sumc[j] += mat[i][j]; } } printf("%d\n", solve()); } }
View Code
相关文章推荐
- HDU Random Maze (欧拉路、费用流)
- Acdream 1171 Matrix sum 上下界费用流
- ACDream 1171 最大费用流,流量不一定最大
- ACDream 1191 - Dragon Maze
- ACdream-1171 Matrix sum, 最大费用最大流
- HDU 4067 Random Maze 费用流
- [费用流] acdream 1171 Matrix sum
- ACdream 1171 Matrix sum (有界费用流)
- Acdream 1191 Dragon Maze bfs
- 【ACDream】1355 Domino in Casino 费用流
- 最小费用最大流的问题
- VK Cup 2017 - Qualification 1 C. Cycle In Maze
- 装修费用“瘦身”三步走
- HDU 5988 Coding Contest(费用流)
- Find a way out of the ClassLoader maze (1)
- HDU 4035 Maze 期望dp
- 迷宫(Maze)问题 递归解
- [SDOI2013]费用流
- 英国前首相布莱尔东莞演讲 费用超1000万(图)
- 【费用流】double模板