费用流。
把每个方格拆成 $T$ 个点,$t$ 时刻一个方格向周围四个方格的 $t + 1$ 的点连一条容量为 $1$ 费用为 $0$ 的边,向自身的 $t + 1$ 连一条容量为 $1$ 费用为该方格最大幸福值的边。
源点向方格为 'S' 的0时刻连一条容量为 $1$ 费用为 $0$ 的边。所有点的 $T - 1$ 时刻向汇点连一条容量为 $1$ 费用为该方格最大幸福值的边。
还有每个格子同时刻不能有多条蛇呆在上面,再把每个点每个时刻拆成两个点,容量为 $1$ 费用为 $0$。跑最大费用最大流即可。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N = ;
  5. const int NN = 1e5 + , M = 5e5 + ;
  6. const int INF = 0x3f3f3f3f;
  7.  
  8. template<class T>
  9. inline void checkmax(T &a, T b) {
  10. if (a < b) a = b;
  11. }
  12. template<class T>
  13. inline void checkmin(T &a, T b) {
  14. if (a > b) a = b;
  15. }
  16.  
  17. struct E {
  18. int v, ne, f, c;
  19. } e[M];
  20. int head[NN], cnt, tol;
  21. int id[N][N][], mp[N][N][];
  22. int dis[NN], path[NN], n, m, z, t;
  23. bool inq[NN];
  24. char str[N][N];
  25. const int dx[] = {, , , -}, dy[] = {-, , , };
  26.  
  27. inline void add(int u, int v, int f, int c) {
  28. e[cnt].v = v; e[cnt].f = f; e[cnt].c = c; e[cnt].ne = head[u]; head[u] = cnt++;
  29. e[cnt].v = u; e[cnt].f = ; e[cnt].c = -c; e[cnt].ne = head[v]; head[v] = cnt++;
  30. }
  31.  
  32. bool spfa(int s, int t) {
  33. for (int i = ; i <= t; i++)
  34. dis[i] = INF, inq[i] = , path[i] = -;
  35. dis[s] = ;
  36. inq[s] = ;
  37. queue<int> que;
  38. que.push(s);
  39. while (!que.empty()) {
  40. int u = que.front(); que.pop();
  41. inq[u] = ;
  42. for (int i = head[u]; ~i; i = e[i].ne) {
  43. int v = e[i].v, c = e[i].c;
  44. if (e[i].f && dis[v] > dis[u] + c) {
  45. dis[v] = dis[u] + c;
  46. path[v] = i;
  47. if (!inq[v]) {
  48. inq[v] = ;
  49. que.push(v);
  50. }
  51. }
  52. }
  53. }
  54. return dis[t] != INF;
  55. }
  56.  
  57. int mcf(int s, int t) {
  58. int ans = ;
  59. while (spfa(s, t)) {
  60. for (int i = path[t]; ~i; i = path[e[i ^ ].v]) e[i].f--, e[i ^ ].f++;
  61. ans += dis[t];
  62. }
  63. return ans;
  64. }
  65.  
  66. int main() {
  67. //freopen("in.txt", "r", stdin);
  68. memset(head, -, sizeof(head));
  69. scanf("%d%d%d%d", &n, &m, &z, &t);
  70. for (int i = ; i <= n; i++)
  71. scanf("%s", str[i] + );
  72. for (int i = ; i <= z; i++) {
  73. int x, y, p, q, h;
  74. scanf("%d%d%d%d%d", &x, &y, &p, &q, &h);
  75. for (int j = p; j < q; j++)
  76. checkmax(mp[x][y][j], h);
  77. }
  78. tol = ;
  79. for (int i = ; i <= n; i++)
  80. for (int j = ; j <= m; j++) if (str[i][j] != '#')
  81. for (int k = ; k < t; k++) {
  82. add(tol, tol + , , );
  83. //cout << tol << ' ' << tol + 1 << endl;
  84. id[i][j][k] = tol;
  85. tol += ;
  86. }
  87. int S = tol + , T = tol + ;
  88. for (int i = ; i <= n; i++)
  89. for (int j = ; j <= m; j++) if (id[i][j][]) {
  90. for (int d = ; d < ; d++) if (id[i + dx[d]][j + dy[d]][])
  91. for (int k = ; k < t - ; k++)
  92. add(id[i][j][k] + , id[i + dx[d]][j + dy[d]][k + ], , );
  93. for (int k = ; k < t - ; k++)
  94. add(id[i][j][k] + , id[i][j][k + ], , -mp[i][j][k]);
  95. add(id[i][j][t - ] + , T, , -mp[i][j][t - ]);
  96. if (str[i][j] == 'S') add(S, id[i][j][], , );
  97. }
  98. printf("%d\n", -mcf(S, T));
  99. return ;
  100. }

Codechef July Challenge 2019 Snake and Apple Tree的更多相关文章

  1. Codechef July Challenge 2019 Division 1题解

    题面 \(CIRMERGE\) 破环成链搞个裸的区间\(dp\)就行了 //quming #include<bits/stdc++.h> #define R register #defin ...

  2. Codechef July Challenge 2019 Hit the Coconuts

    假设现在有一堆数,我想要保证能取出一个,至少需要敲 (数的个数)*(这些数里的最小值)那么把这些数从大到小排序,$dp[i][j]$ 表示前 $i$ 个里面保证能取出 $j$ 个需要敲的次数.$dp[ ...

  3. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  4. [codechef July Challenge 2017] Pishty and tree

    PSHTTR: Pishty 和城堡题目描述Pishty 是生活在胡斯特市的一个小男孩.胡斯特是胡克兰境内的一个古城,以其中世纪风格的古堡和非常聪明的熊闻名全国.胡斯特的镇城之宝是就是这么一座古堡,历 ...

  5. Codechef December Challenge 2014 Chef and Apple Trees 水题

    Chef and Apple Trees Chef loves to prepare delicious dishes. This time, Chef has decided to prepare ...

  6. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

  7. Codechef April Challenge 2019 Division 2

    Maximum Remaining 题意:给n个数,取出两个数$a_{i}$,$a_{j}$,求$a_{i}\% a_{j}$取模的最大值 直接排个序,第二大(严格的第二大)模第一大就是答案了. #i ...

  8. Codechef November Challenge 2019 Division 1

    Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...

  9. Codechef October Challenge 2019 Division 1

    Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...

随机推荐

  1. 『数 变进制状压dp』

    数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100 ...

  2. Github Markdown 图片如何并排显示

    Github Markdown 图片如何并排显示   要一张图片接着一张图片的写,中间不能有换行.如果换行的话则图片也换行 正确的写法: ![描述](图片链接)![描述](图片链接)![描述](图片链 ...

  3. SetWindowLong函数GetWindowLong函数

    这两个函数具体应用如下:SetWindowLong函数GetWindowLong函数 Delphi窗口化游戏 var Thwnd:HWND;//声明变量 句柄变量 devmodel1:DEVMODE; ...

  4. SQL根据指定节点ID获取所有父级节点和子级节点

    --根据指定节点ID获取所有子节点-- WITH TEMP AS ( SELECT * FROM table_name WHERE Id=' --表的主键ID UNION ALL SELECT T0. ...

  5. Options of the DB storage of prometheus

    参考: // Options of the DB storage. type Options struct { // The timestamp range of head blocks after ...

  6. soup.select的用法

    1.通过标签选择 # 选择所有title标签 soup.select("title") # 选择所有p标签中的第三个标签 soup.select("p:nth-of-ty ...

  7. spark的存储系统--BlockManager源码分析

    spark的存储系统--BlockManager源码分析 根据之前的一系列分析,我们对spark作业从创建到调度分发,到执行,最后结果回传driver的过程有了一个大概的了解.但是在分析源码的过程中也 ...

  8. xcode11新项目删除main.storyboard 两种方法

    方法一 心急的童鞋按照老操作完成后再按照如下操作即可 /** 弃用storboard 1.info.plist去除 <key>UIApplicationSceneManifest</ ...

  9. vue与webpack开发环境搭建:从无到有

    一个vue从无到有的搭建过程. 一.不论是webpack还是vue,最初的第一步就是安装node.js.它是基石. 从官网下载你需要的安装包:官网下载链接:http://nodejs.cn/downl ...

  10. 《JavaScript高级程序设计》笔记:新兴的API

    requestAnimationFrame() 大多数电脑显示器的刷新频率60HZ,大概相当于每秒钟重绘60次.因此,最平滑动画的最佳循环间隔是1000ms/60,约等于17ms. mozReques ...