Solution

最小割.

参考BZOJ 3144切糕

在那道题的基础上将建图方法稍作变形: 我们对格子进行黑白染色, 对于两个格子之和\(\le k\)的限制, 就可以确定其中一个是白色格子, 一个是黑色格子. 我们让黑色格子和白色格子的点的顺序相反, 就可以表示限制了.

目前的代码还是WA的.

#include <cstdio>
#include <cctype>
#include <vector>
#include <deque>
#include <algorithm> namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1;
char c;
while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
const int N = 50, M = 50, INF = (int)1e9;
int D[N][M], R[N][M];
struct graph
{
struct node;
struct edge
{
node *v; int cap; edge *op;
};
struct node
{
std::vector<edge*> edg;
int dep;
inline node()
{
edg.clear();
}
}nd[N][M][11], *S, *T;
inline graph()
{
S = new node; T = new node;
}
inline void addEdge(node *u, node *v, int cap)
{
edge *a = new edge, *b = new edge;
a->v = v; a->cap = cap; a->op = b;
b->v = u; b->cap = 0; b->op = a;
u->edg.push_back(a); v->edg.push_back(b);
}
int cnt;
void clear(node *u)
{
u->dep = - cnt;
for(auto edg : u->edg) if(edg->v->dep != -cnt) clear(edg->v);
}
inline int BFS()
{
++ cnt; clear(S); S->dep = 0;
static std::deque<node*> que; que.clear();
que.push_back(S);
for(; ! que.empty(); que.pop_front())
{
node *u = que.front();
for(auto edg : u->edg) if(edg->cap && edg->v->dep == - cnt) edg->v->dep = u->dep + 1, que.push_back(edg->v);
}
return T->dep != - cnt;
}
int DFS(node *u, int flw)
{
if(u == T) return flw;
int flowSum = 0;
for(auto edg : u->edg) if(edg->cap && edg->v->dep == u->dep + 1)
{
int currentFlow = DFS(edg->v, std::min(edg->cap, flw - flowSum));
flowSum += currentFlow;
edg->cap -= currentFlow; edg->op->cap += currentFlow;
if(flowSum == flw) return flowSum;
}
if(! flowSum) u->dep = -1;
return flowSum;
}
inline int dinic()
{
cnt = 0;
int res = 0;
while(BFS())
res += DFS(S, INF);
return res;
}
}G;
int main()
{ #ifndef ONLINE_JUDGE freopen("matrix.in", "r", stdin);
freopen("matrix.out", "w", stdout); #endif using namespace Zeonfai;
int n = getInt(), m = getInt();
for(int i = 0; i < n - 1; ++ i) for(int j = 0; j < m; ++ j) D[i][j] = getInt();
for(int i = 0; i < n; ++ i) for(int j = 0; j < m - 1; ++ j) R[i][j] = getInt();
for(int i = 0; i < n; ++ i) for(int j = 0; j < m; ++ j)
{
if(i ^ j & 1)
{
G.addEdge(G.S, &G.nd[i][j][9], INF);
for(int k = 9; k >= 1; -- k) G.addEdge(&G.nd[i][j][k], &G.nd[i][j][k - 1], 10 - k);
G.addEdge(&G.nd[i][j][0], G.T, INF);
for(int k = 0; k <= 9; ++ k)
{
if(i + 1 < n && D[i][j] - k <= 10 && D[i][j] - k >= 1) G.addEdge(&G.nd[i + 1][j][D[i][j] - k], &G.nd[i][j][k], INF);
if(j + 1 < m && R[i][j] - k <= 10 && R[i][j] - k >= 1) G.addEdge(&G.nd[i][j + 1][R[i][j] - k], &G.nd[i][j][k], INF);
}
}
else
{
G.addEdge(G.S, &G.nd[i][j][1], INF);
for(int k = 1; k <= 9; ++ k) G.addEdge(&G.nd[i][j][k], &G.nd[i][j][k + 1], 10 - k);
G.addEdge(&G.nd[i][j][10], G.T, INF);
for(int k = 1; k <= 10; ++ k)
{
if(i + 1 < n && D[i][j] - k <= 9 && D[i][j] - k >= 0) G.addEdge(&G.nd[i][j][k], &G.nd[i + 1][j][D[i][j] - k], INF);
if(j + 1 < m && R[i][j] - k <= 9 && R[i][j] - k >= 0) G.addEdge(&G.nd[i][j][k], &G.nd[i][j + 1][R[i][j] - k], INF);
}
}
}
printf("%d\n", n * m * 10 - G.dinic());
}

2016北京集训测试赛(六)Problem B: 矩阵的更多相关文章

  1. 2016北京集训测试赛(十六)Problem C: ball

    Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sq ...

  2. 2016北京集训测试赛(十六)Problem B: river

    Solution 这题实际上并不是构造题, 而是一道网络流. 我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样. ...

  3. 2016北京集训测试赛(十六)Problem A: 任务安排

    Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...

  4. 2016北京集训测试赛(六)Problem A: 冒泡排序

    Solution 观察冒泡排序的过程. 我们注意到, 每一轮的排序都会使得每个数后面比它小的数的个数减\(1\). 我们用\(f(n, m)\)表示对\(1\)到\(n\)的一个排列进行冒泡排序, 满 ...

  5. 【2016北京集训测试赛(十六)】 River (最大流)

    Description  Special Judge Hint 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. 题解 题目大意:给定两组点,每组有$n$个点,有若干条跨组 ...

  6. 2016北京集训测试赛(十七)Problem C: 数组

    Solution 线段树好题. 我们考虑用last[i]表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \ ...

  7. 2016北京集训测试赛(十七)Problem B: 银河战舰

    Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...

  8. 2016北京集训测试赛(十七)Problem A: crash的游戏

    Solution 相当于要你计算这样一个式子: \[ \sum_{x = 0}^m \left( \begin{array}{} m \\ x \end{array} \right) \left( \ ...

  9. BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记

    Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...

随机推荐

  1. v-model 的修饰符

    1..trim 自动过滤输入内容最开始 和 最后的 空格,中间的会保留一个空格,多的会被过滤掉 2..lazy 一般情况下,在input的 v-model是一直在同步 输入的内容与显示的内容,不过再添 ...

  2. TypeError: cannot perform reduce with flexible type

    想要解决这个错误,最好先明白numpy数据类型的dtype转换 生成一个浮点数组 a=np.random.random(4) 输出 a array([0.0945377,0.52199916,0.62 ...

  3. Js中的假值_ES5中定义的ToBoolean方法强制类型转换后值为false

    你不知道的Javascript(中)--ToBoolean javascript中的值可以分为以下两类: 1.可以被强制类型转换为false的值 2.其他(被强制类型转换为true的值) 假值---以 ...

  4. IOS开发---菜鸟学习之路--(十八)-利用代理实现向上一级页面传递数据

    其实我一开始是想实现微信的修改个人信息那样的效果 就是点击昵称,然后跳转到另外一个页面输入信息 但是细想发现微信的话应该是修改完一个信息后就保存了 而我做的项目可能需要输入多个数据之后再点击提交的. ...

  5. PHP 与 Redis 入门教程

    Redis 官方推荐的 PHP 客户端是 Predis 和 phpredis. 前者是完全使用 PHP 代码实现的原生客户端,而后者则是使用 C 语言编写的 PHP 扩展.在功能上两者区别并不大,就性 ...

  6. random.nextInt方法用法

    1.不带参数的nextInt()会生成所有有效的整数(包含正数,负数,0) 2.带参的nextInt(int x)则会生成一个范围在0~x(不包含X)内的任意正整数 例如:int x=new Rand ...

  7. JAVA使用JDBC连接MySQL数据库 一

    public class JDBCTest { public static void main(String[] args){ String driver = "com.mysql.jdbc ...

  8. [CQOI2014][bzoj3507] 通配符匹配 [字符串hash+dp]

    题面 传送门 思路 0x01 KMP 一个非常显然而优秀的想法:把模板串按照'*'分段,然后对于每一段求$next$,'?'就当成可以对于任意字符匹配就行了 对于每个文本串,从前往后找第一个可以匹配的 ...

  9. [HNOI2014][bzoj3572] 世界树 [虚树+dp]

    题面: 传送门 思路: 一道虚树的好题,是很多虚树博客的入门题目 但是我认为这道题目出的难点和亮点不在于虚树,而在于建出虚树以后dp的思路与实现 下文中为方便描述,用势力范围来表示一个“议事处”管辖的 ...

  10. [USACO Section 5.3]量取牛奶 Milk Measuring (动态规划,背包$dp$)

    题目链接 Solution 完全背包 \(dp\) , 同时再加一个数组 \(v[i][j]\) 记录当总和为\(j\) 时第 \(i\) 种物品是否被选. 为保证从小到大和字典序,先将瓶子按大小排序 ...