博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3422 【最大费用】.cpp
阅读量:5080 次
发布时间:2019-06-12

本文共 3414 字,大约阅读时间需要 11 分钟。

题意:

给出一个每一格带值的矩阵

每一次只可以从左上角走到右下角

问走过k次后最多能得到多少值

P.S 走过的格子值会变成0

输入:

  给出一个n 和 k

  给出n*n 矩阵

 

思路:

  因为求的是最大值

  所以应该求最长距离..把最小路径改成求最大路径

  <相应改变的就是松弛操作 和 dis的初始状态>

  

  为了保证每个点只取一次值 并且 可以经过多次

  就进行拆点 然后对应点之间加两条边 ①. 容量为1 费用为该点的值 ②. 容量为INF 费用为0

  ①边保证了该点走过后变为0值 ②边保证该点可以经过多次

 

  还有超级源点跟每个点之间连边 容量为k 费用为0

  超级汇点和每个拆点之间连边 容量为k 费用为0

 

Tips:

  加边的时候记得判断边界情况..

  还有因为拆点了 和 加了超级源点和汇点  边数就要相应增多..

  循环队列也要开大点..  

 

Code:

 

View Code
1 #include 
2 #include
3 #include
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 }

 

 

 

题目链接:

转载于:https://www.cnblogs.com/Griselda/archive/2012/10/02/2710536.html

你可能感兴趣的文章
HDU 5458 Stability
查看>>
左手坐标系和右手坐标系
查看>>
solr后台操作Documents之增删改查
查看>>
http://yusi123.com/
查看>>
文件文本的操作
查看>>
Ubuntu linux下gcc版本切换
查看>>
记一次Web服务的性能调优
查看>>
jQuery.form.js使用
查看>>
(转)linux sort,uniq,cut,wc命令详解
查看>>
关于ExecuteNonQuery执行的返回值(SQL语句、存储过程)
查看>>
UVa540 Team Queue(队列queue)
查看>>
mysql数据增删改查
查看>>
shell中下载最新版本或指定版本的办法(Dockerfile 中通用)
查看>>
极客时间-左耳听风-程序员攻略-分布式架构工程设计
查看>>
akka之种子节点
查看>>
不知道做什么时
查看>>
matlab 给某一列乘上一个系数
查看>>
密码学笔记——培根密码
查看>>
Screening technology proved cost effective deal
查看>>
MAC 上升级python为最新版本
查看>>