Codechef July Challenge 2019 Snake and Apple Tree
费用流。
把每个方格拆成 $T$ 个点,$t$ 时刻一个方格向周围四个方格的 $t + 1$ 的点连一条容量为 $1$ 费用为 $0$ 的边,向自身的 $t + 1$ 连一条容量为 $1$ 费用为该方格最大幸福值的边。
源点向方格为 'S' 的0时刻连一条容量为 $1$ 费用为 $0$ 的边。所有点的 $T - 1$ 时刻向汇点连一条容量为 $1$ 费用为该方格最大幸福值的边。
还有每个格子同时刻不能有多条蛇呆在上面,再把每个点每个时刻拆成两个点,容量为 $1$ 费用为 $0$。跑最大费用最大流即可。
- #include <bits/stdc++.h>
- using namespace std;
- const int N = ;
- const int NN = 1e5 + , M = 5e5 + ;
- const int INF = 0x3f3f3f3f;
- template<class T>
- inline void checkmax(T &a, T b) {
- if (a < b) a = b;
- }
- template<class T>
- inline void checkmin(T &a, T b) {
- if (a > b) a = b;
- }
- struct E {
- int v, ne, f, c;
- } e[M];
- int head[NN], cnt, tol;
- int id[N][N][], mp[N][N][];
- int dis[NN], path[NN], n, m, z, t;
- bool inq[NN];
- char str[N][N];
- const int dx[] = {, , , -}, dy[] = {-, , , };
- inline void add(int u, int v, int f, int c) {
- e[cnt].v = v; e[cnt].f = f; e[cnt].c = c; e[cnt].ne = head[u]; head[u] = cnt++;
- e[cnt].v = u; e[cnt].f = ; e[cnt].c = -c; e[cnt].ne = head[v]; head[v] = cnt++;
- }
- bool spfa(int s, int t) {
- for (int i = ; i <= t; i++)
- dis[i] = INF, inq[i] = , path[i] = -;
- dis[s] = ;
- inq[s] = ;
- queue<int> que;
- que.push(s);
- while (!que.empty()) {
- int u = que.front(); que.pop();
- inq[u] = ;
- for (int i = head[u]; ~i; i = e[i].ne) {
- int v = e[i].v, c = e[i].c;
- if (e[i].f && dis[v] > dis[u] + c) {
- dis[v] = dis[u] + c;
- path[v] = i;
- if (!inq[v]) {
- inq[v] = ;
- que.push(v);
- }
- }
- }
- }
- return dis[t] != INF;
- }
- int mcf(int s, int t) {
- int ans = ;
- while (spfa(s, t)) {
- for (int i = path[t]; ~i; i = path[e[i ^ ].v]) e[i].f--, e[i ^ ].f++;
- ans += dis[t];
- }
- return ans;
- }
- int main() {
- //freopen("in.txt", "r", stdin);
- memset(head, -, sizeof(head));
- scanf("%d%d%d%d", &n, &m, &z, &t);
- for (int i = ; i <= n; i++)
- scanf("%s", str[i] + );
- for (int i = ; i <= z; i++) {
- int x, y, p, q, h;
- scanf("%d%d%d%d%d", &x, &y, &p, &q, &h);
- for (int j = p; j < q; j++)
- checkmax(mp[x][y][j], h);
- }
- tol = ;
- for (int i = ; i <= n; i++)
- for (int j = ; j <= m; j++) if (str[i][j] != '#')
- for (int k = ; k < t; k++) {
- add(tol, tol + , , );
- //cout << tol << ' ' << tol + 1 << endl;
- id[i][j][k] = tol;
- tol += ;
- }
- int S = tol + , T = tol + ;
- for (int i = ; i <= n; i++)
- for (int j = ; j <= m; j++) if (id[i][j][]) {
- for (int d = ; d < ; d++) if (id[i + dx[d]][j + dy[d]][])
- for (int k = ; k < t - ; k++)
- add(id[i][j][k] + , id[i + dx[d]][j + dy[d]][k + ], , );
- for (int k = ; k < t - ; k++)
- add(id[i][j][k] + , id[i][j][k + ], , -mp[i][j][k]);
- add(id[i][j][t - ] + , T, , -mp[i][j][t - ]);
- if (str[i][j] == 'S') add(S, id[i][j][], , );
- }
- printf("%d\n", -mcf(S, T));
- return ;
- }
Codechef July Challenge 2019 Snake and Apple Tree的更多相关文章
- Codechef July Challenge 2019 Division 1题解
题面 \(CIRMERGE\) 破环成链搞个裸的区间\(dp\)就行了 //quming #include<bits/stdc++.h> #define R register #defin ...
- Codechef July Challenge 2019 Hit the Coconuts
假设现在有一堆数,我想要保证能取出一个,至少需要敲 (数的个数)*(这些数里的最小值)那么把这些数从大到小排序,$dp[i][j]$ 表示前 $i$ 个里面保证能取出 $j$ 个需要敲的次数.$dp[ ...
- Codechef April Challenge 2019 游记
Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...
- [codechef July Challenge 2017] Pishty and tree
PSHTTR: Pishty 和城堡题目描述Pishty 是生活在胡斯特市的一个小男孩.胡斯特是胡克兰境内的一个古城,以其中世纪风格的古堡和非常聪明的熊闻名全国.胡斯特的镇城之宝是就是这么一座古堡,历 ...
- 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 ...
- CodeChef April Challenge 2019题解
传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...
- Codechef April Challenge 2019 Division 2
Maximum Remaining 题意:给n个数,取出两个数$a_{i}$,$a_{j}$,求$a_{i}\% a_{j}$取模的最大值 直接排个序,第二大(严格的第二大)模第一大就是答案了. #i ...
- Codechef November Challenge 2019 Division 1
Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...
- Codechef October Challenge 2019 Division 1
Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...
随机推荐
- 『数 变进制状压dp』
数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100 ...
- Github Markdown 图片如何并排显示
Github Markdown 图片如何并排显示 要一张图片接着一张图片的写,中间不能有换行.如果换行的话则图片也换行 正确的写法:  # 选择所有p标签中的第三个标签 soup.select("p:nth-of-ty ...
- spark的存储系统--BlockManager源码分析
spark的存储系统--BlockManager源码分析 根据之前的一系列分析,我们对spark作业从创建到调度分发,到执行,最后结果回传driver的过程有了一个大概的了解.但是在分析源码的过程中也 ...
- xcode11新项目删除main.storyboard 两种方法
方法一 心急的童鞋按照老操作完成后再按照如下操作即可 /** 弃用storboard 1.info.plist去除 <key>UIApplicationSceneManifest</ ...
- vue与webpack开发环境搭建:从无到有
一个vue从无到有的搭建过程. 一.不论是webpack还是vue,最初的第一步就是安装node.js.它是基石. 从官网下载你需要的安装包:官网下载链接:http://nodejs.cn/downl ...
- 《JavaScript高级程序设计》笔记:新兴的API
requestAnimationFrame() 大多数电脑显示器的刷新频率60HZ,大概相当于每秒钟重绘60次.因此,最平滑动画的最佳循环间隔是1000ms/60,约等于17ms. mozReques ...