又是一个看了题解以后还坑了一天的题…… 结果最后发现是抄代码的时候少写了一个负号。

题意:

  有一个n*m的网格,其中每个格子上都有0~9的数字。现在你可以玩K次游戏。

  一次游戏是这样定义的: 你可以选任意之前没有走过的格子作为起点。然后走任意步,其中每一步你可以向右或者向下走任意格。假如从(x1, y1)走到(x2, y2)需要花费能量|x1-x2|+|y1-y2|-1,如果这一步和上一步格子的数字相同,那么可以获得格子上相应数字的能量。能量可以为负值。

  问你,在K次以内走完所以格子最多能得到多少能量,若走不完,输出-1 。

思路:(直接抄题解)

  最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <algorithm>
  7. #include <string>
  8. #include <queue>
  9. #include <stack>
  10. #include <vector>
  11. #include <map>
  12. #include <set>
  13. #include <functional>
  14. #include <time.h>
  15.  
  16. using namespace std;
  17.  
  18. const int INF = <<;
  19. const int MAXN = ;
  20.  
  21. struct Edge {
  22. int from, to, cap, flow, cost;
  23. Edge(int from, int to, int cap, int flow, int cost)
  24. : from(from), to(to), cap(cap), flow(flow), cost(cost) {}
  25. };
  26.  
  27. struct MCMF {
  28. int n, m, s, t;
  29. vector<Edge> edges;
  30. vector<int> G[MAXN];
  31.  
  32. int inq[MAXN];
  33. int d[MAXN];
  34. int p[MAXN];
  35. int a[MAXN];
  36. int cnt[MAXN];
  37.  
  38. void init(int n) {
  39. this->n = n;
  40. for (int i = ; i < n; i++) G[i].clear();
  41. edges.clear();
  42. }
  43.  
  44. void addEdge(int from, int to, int cap, int cost) {
  45. edges.push_back(Edge(from, to, cap, , cost));
  46. edges.push_back(Edge(to, from, , , -cost));
  47. m = edges.size();
  48. G[from].push_back(m-);
  49. G[to].push_back(m-);
  50. }
  51.  
  52. bool BellmanFord(int s, int t, int &flow, int &cost) {
  53. for (int i = ; i < n; i++) d[i] = INF;
  54. memset(inq, , sizeof(inq));
  55. memset(cnt, , sizeof(cnt));
  56. d[s] = ; inq[s] = ; p[s] = ; a[s] = INF;
  57. bool flag = false;
  58. queue<int> Q;
  59. Q.push(s);
  60. while (!Q.empty()) {
  61. int u = Q.front(); Q.pop();
  62. //printf("u: %d %d\n", u, Q.size());
  63. inq[u] = ;
  64. for (int i = ; i < G[u].size(); i++) {
  65. Edge &e = edges[G[u][i]];
  66. if (e.cap>e.flow && d[e.to] > d[u]+e.cost) {
  67. cnt[e.to] = cnt[u]+;
  68. if (cnt[e.to]>=n) {flag = true; break; }
  69. //printf("u: %d v: %d\n d[u]: %d d[v]: %d cost: %d\ncap: %d flow: %d\n", u, e.to, d[u], d[e.to], e.cost, e.cap, e.flow);
  70. d[e.to] = d[u] + e.cost;
  71. p[e.to] = G[u][i];
  72. a[e.to] = min(a[u], e.cap-e.flow);
  73. if (!inq[e.to]) { Q.push(e.to); inq[e.to] = ; }
  74. }
  75. }
  76. if (flag)break;
  77. }
  78. if (d[t]==INF) return false;
  79. flow += a[t];
  80. cost += d[t]*a[t];
  81. int u = t;
  82. while (u!=s) {
  83. edges[p[u]].flow += a[t];
  84. edges[p[u]^].flow -= a[t];
  85. u = edges[p[u]].from;
  86. }
  87. return true;
  88. }
  89.  
  90. pair<int, int> MinCost(int s, int t) {
  91. int flow = , cost = ;
  92. while (BellmanFord(s, t, flow, cost)) ;
  93. return make_pair(flow, cost);
  94. }
  95. void print(){
  96. for(int i=;i<n;i++){
  97. printf("%d :",i);
  98. for(int j=;j<G[i].size();j++)
  99. printf("(%d %d %d)",edges[G[i][j]].to,edges[G[i][j]].cap,edges[G[i][j]].cost);
  100. puts("");
  101. }
  102. }
  103. }solver;
  104.  
  105. int N, M, K;
  106. int grid[][];
  107.  
  108. void solve() {
  109. char tmp[];
  110. scanf("%d%d%d", &N, &M, &K);
  111. for (int i = ; i < N; i++) {
  112. scanf("%s", tmp);
  113. for (int j = ; j < M; j++) {
  114. grid[i][j] = tmp[j] - '';
  115. }
  116. }
  117. int num = N*M; //总的格点数
  118. //格点的编号规则: grid[i][j] = i*M + j
  119.  
  120. //建图:
  121. //编号规则:
  122. /*
  123. 0~num : 每个点的第一部分
  124. num~2*num-1 : 每个点的第二部分
  125. 2*num: 原点
  126. 2*num+1 : 额外点
  127. 2*num+2 :
  128. */
  129. int st = *num, ad = st+, ed = ad+;
  130. solver.init(*num+);
  131. for (int i = ; i < num; i++) { //原点到第一部分的每个点有一条容量为1,费用为0的边
  132. solver.addEdge(st, i, , );
  133. }
  134. for (int i = num; i < *num; i++) { //每个点的第二部分到汇点有一个容量为1,费用为0
  135. solver.addEdge(i, ed, , );
  136. }
  137. solver.addEdge(st, ad, K, );
  138. for (int i = num; i < *num; i++) { //额外点到每个点的第二部分的边
  139. solver.addEdge(ad, i, , );
  140. }
  141. for (int i = ; i < N; i++)
  142. for (int j = ; j < M; j++) { //对于每一个点
  143. for (int x = i+; x < N; x++) {
  144. int cost = x-i-;
  145. if (grid[i][j]==grid[x][j])
  146. cost -= grid[i][j];
  147. solver.addEdge(i*M+j, num+x*M+j, , cost);
  148. }
  149.  
  150. for (int y = j+; y < M; y++) {
  151. int cost = y-j-;
  152. if (grid[i][j]==grid[i][y])
  153. cost -= grid[i][j];
  154. solver.addEdge(i*M+j, num+i*M+y, , cost);
  155. }
  156. }
  157. //puts("ok");
  158. //solver.print();
  159.  
  160. pair<int, int> ans = solver.MinCost(st, ed);
  161. if (ans.first==num)
  162. printf("%d\n", -ans.second);
  163. else
  164. puts("-1");
  165. }
  166.  
  167. int main() {
  168. #ifdef Phantom01
  169. freopen("HDU4862.txt", "r", stdin);
  170. #endif //Phantom01
  171.  
  172. int Case;
  173. scanf("%d", &Case);
  174. for (int i = ; i <= Case; i++) {
  175. printf("Case %d : ", i);
  176. solve();
  177. }
  178.  
  179. return ;
  180. }

HDU4862

  

HDU 4862 Jump 费用流的更多相关文章

  1. HDU 4862(费用流)

    Problem Jump (HDU4862) 题目大意 给定一个n*m的矩形(n,m≤10),每个矩形中有一个0~9的数字. 一共可以进行k次游戏,每次游戏可以任意选取一个没有经过的格子为起点,并且跳 ...

  2. HDU 4862 Jump(更多的联合培训学校1)(最小费用最大流)

    职务地址:pid=4862">HDU4862 最小费用流做的还是太少. 建图想不出来. . . 直接引用官方题解的话吧... 最小K路径覆盖的模型.用费用流或者KM算法解决,构造二部图 ...

  3. Mining Station on the Sea HDU - 2448(费用流 || 最短路 && hc)

    Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  4. Coding Contest HDU - 5988(费用流)

    题意: 有n个区域和m条路,每个区域有a[i]个人和b[i]个食物,然后是m条路连接两个区域,这条路容量为cap,这条路断掉的概率为p,第一个经过的时候一定不会断,后面的人有概率p会断,现在需要所有人 ...

  5. HDU 4862 JUMP 最小费用最大流

    2014 多校的B题,由于我不怎么搞图论,当时碰到这个题目,我怎么想都没往网络流方面弄,不过网络流真的是个好东西,对于状态多变,无法用动规或者数据结构来很好表示的时候,非常有用 这个题目要求每个点一定 ...

  6. HDU 4862 Jump(最小K路径覆盖)

    输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点 ...

  7. hdu 4322 最大费用流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4322 #include <cstdio> #include <cstring> ...

  8. HDU 4862 Jump 任意起点最大权K链不相交覆盖

    你可以从任意起点开始起跳最多K次 每次跳你可以选择往右或者往下跳 从(x1,y1)跳到(x2,y2) 消耗的能量是曼哈顿距离-1 但是如果每次跳的起点和终点格子里的数字是相同的为X的话你会得到X能量 ...

  9. Going Home HDU - 1533 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...

随机推荐

  1. SQLServer 错误: 15404,维护计划无法执行

    错误症状: D:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG下面的ERROELOG,用文本打,查看运行维维计划不成功是生成的错误日志详细信 ...

  2. 【原创】使用Kettle的一些心得和经验

    用kettle做etl也有段时间了,遇到很多问题,总结了一下. [关于版本的问题] kettle常用的版本有4.1和4.4,对于4.1版本: 1.该版本的兼容性有点差,在某些机器上运行会启动失败,或者 ...

  3. 【原创】Apache和Tomcat实现动静分离

    集群中每个节点都启用了页面静态化功能,所以,为了防止单个节点刷新造成找不到页面问题,将每个节点刷新的页面都放入apache虚拟目录下,由apache统一来处理.静态页面由apache处理,动态页面仍然 ...

  4. 优动漫PAINT-简单的树、叶教学

    如题,简单.好用:其实说的还是一个观察的事.看你是否足够细心,对于树叶的生长.枝桠和树干的关系是否了解咯. 对于这样的树枝丫和叶子完全可以使用优动漫PAINT完成,简单又快捷,软件下载:www.don ...

  5. Mac 如何修改Mac系统的默认截图路径

    step 1 :打在桌面或者其他任意位置创建一个文件夹:截图图库.我创建的路径是:/Users/yilin/Documents/截图图库(仅供参考) step 2:打开终端,输入以下命令:defaul ...

  6. 路飞学城Python-Day12

    7月10日安排  完成所有函数作业和思维导图整理   [45.函数-生成器] 如果数据是有规律的,就可以先生成一个数据,等数据执行的时候再执行,也就是在真正调用数据之前,拿到数据的生成规律,而是拿到生 ...

  7. (WC2018模拟十二)【FJOI2016集训Day7T2】点对游戏

    题解: 还好...看懂题目就好做了.(Orzdyh) 首先选择的点是等概率随机的,也就是说每种选择结果的概率都是一样的,所以选择一个点的时候已经选择的点不会有影响,那么就可以直接算出点对个数再求总体的 ...

  8. matlab Time-domain analysis 渐进式或者实时获取仿真值

    首先准备一个传递函数sys, 然后使用lsim(sys,u,t,x0)函数(通用的时序分析的函数) u: The input u is an array having as many rows as ...

  9. LaTeX 设置字体颜色

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50240179 需要包含宏包: \use ...

  10. Eclipse集成Git插件及使用

    目录(?)[+] 1 Git插件安装 11 下载插件 2 Git提交代码 21 建git的本地仓库 第一种 第二种 项目创建本地仓库后 如图 22 提交本地仓库 23 提交远程仓库 3 Git下载代码 ...