题意:
给出一个每一格带值的矩阵
每一次只可以从左上角走到右下角
问走过k次后最多能得到多少值
P.S 走过的格子值会变成0
输入:
给出一个n 和 k
给出n*n 矩阵
思路:
因为求的是最大值
所以应该求最长距离..把最小路径改成求最大路径
<相应改变的就是松弛操作 和 dis的初始状态>
为了保证每个点只取一次值 并且 可以经过多次
就进行拆点 然后对应点之间加两条边 ①. 容量为1 费用为该点的值 ②. 容量为INF 费用为0
①边保证了该点走过后变为0值 ②边保证该点可以经过多次
还有超级源点跟每个点之间连边 容量为k 费用为0
超级汇点和每个拆点之间连边 容量为k 费用为0
Tips:
加边的时候记得判断边界情况..
还有因为拆点了 和 加了超级源点和汇点 边数就要相应增多..
循环队列也要开大点..
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define clr(x) memset(x, 0, sizeof(x)) 6 const int INF = 0x1f1f1f1f; 7 const int MAXN = 6000; 8 const int MAXM = 100010; 9 struct Edge 10 { 11 int from; 12 int to; 13 int next; 14 int c; 15 int f; 16 }edge[MAXM]; 17 int head[MAXN]; 18 int tot; 19 int n, k; 20 int dis[MAXN], pre[MAXN]; 21 bool flag[MAXN]; 22 23 void add(int s, int u, int c, int f) 24 { 25 edge[tot].from = s; 26 edge[tot].to = u; 27 edge[tot].next = head[s]; 28 edge[tot].f = f; 29 edge[tot].c = c; 30 head[s] = tot++; 31 32 edge[tot].from = u; 33 edge[tot].to = s; 34 edge[tot].f = 0; 35 edge[tot].c = -c; 36 edge[tot].next = head[u]; 37 head[u] = tot++; 38 } 39 40 int que[MAXN*100]; 41 bool spfa(int s, int e) 42 { 43 int qout, qin; 44 clr(flag); 45 memset(pre, 0xff, sizeof(pre)); 46 memset(dis, 0xff, sizeof(dis)); 47 qin = qout = 0; 48 que[qin++] = s; 49 dis[s] = 0; 50 flag[s] = true; 51 while(qin != qout) { 52 int tmpe = que[qout++]; 53 flag[tmpe] = false; 54 for(int i = head[tmpe]; i != -1; i = edge[i].next) { 55 int ne = edge[i].to; 56 if(edge[i].f && dis[ne]-dis[tmpe] < edge[i].c) { 57 dis[ne] = dis[tmpe]+edge[i].c; 58 pre[ne] = i; 59 if(!flag[ne]) { 60 flag[ne] = true; 61 que[qin++] = ne; 62 } 63 } 64 } 65 } 66 67 if(dis[e] == -1) 68 return false; 69 else return true; 70 } 71 72 int min_c_f(int s, int e) 73 { 74 int u, mn; 75 int ans_f = 0, ans_c = 0; 76 while(spfa(s, e)) 77 { 78 u = pre[e]; 79 mn = INF; 80 while(u != -1) { 81 mn = min(edge[u].f, mn); 82 u = pre[edge[u].from]; 83 } 84 u = pre[e]; 85 while(u != -1) { 86 edge[u].f -= mn; 87 edge[u^1].f += mn; 88 u = pre[edge[u].from]; 89 } 90 ans_c += dis[e]*mn; 91 ans_f += mn; 92 } 93 return ans_c; 94 } 95 96 int main() 97 { 98 int i, j; 99 int w, t; 100 while(scanf("%d %d", &n, &k) != EOF) 101 { 102 tot = 0, t = n*n; 103 memset(head, 0xff, sizeof(head)); 104 clr(flag), clr(dis), clr(pre); 105 106 for(i = 1; i <= t; ++i) { 107 scanf("%d", &w); 108 add(i, i+t, w, 1); 109 add(i, i+t, 0, INF); 110 if(i%n != 0) 111 add(i+t, i+1, 0, INF); 112 if(i <= t-n) 113 add(i+t, i+n, 0, INF); 114 } 115 116 add(0, 1, 0, k); 117 add(2*t, 2*t+1, 0, k); 118 int ans = min_c_f(0, 2*t+1); 119 printf("%d\n", ans); 120 } 121 return 0; 122 }