题目描述

有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。

输入输出格式

输入格式:

第一行包含两个整数n,m(1≤n,m≤20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0..9数字的字符串,表示每个格子参与交换的次数上限。

输出格式:

输出仅一行,为最小交换总次数。如果无解,输出−1。

解法:

一眼费用流系列…然而这题的处理有点诡异,首先要拆点将点的限制转化为边的限制,S→INi,OUTi→T。IN→OUT的权值是多少?分三种情况讨论:

  1. 既不是起始也不是结束状态:⌊n2⌋
  2. 既是起始也是结束状态:⌊n+22⌋
  3. 是起始或结束状态:⌊n+12⌋
#include <bits/stdc++.h>
using namespace std;const int MAXN = 2005;
struct node {int to, next, f, c, neg;
} edge[MAXN*40];
int head[MAXN], top = 0;
void push(int i, int j, int k, int l)
{if (i*j == 0) return;++top, edge[top] = (node) {j, head[i], k, l, top+1}, head[i] = top;++top, edge[top] = (node) {i, head[j], 0, -l, top-1}, head[j] = top;
}int vis[MAXN], dis[MAXN], S = 2001, T = 2002;
queue<int> que;
int pre[MAXN], pre_edge[MAXN];
const int INF = 233333333;bool spfa()
{memset(dis, 127/3, sizeof dis);memset(pre, 0, sizeof pre);vis[S] = 1, que.push(S), dis[S] = 0;while (!que.empty()) {int tp = que.front(); que.pop(), vis[tp] = 0;for (int i = head[tp]; i; i = edge[i].next) {if (edge[i].f == 0 || dis[edge[i].to] <= dis[tp] + edge[i].c) continue;int to = edge[i].to, c = edge[i].c;dis[to] = dis[tp] + c, pre[to] = tp, pre_edge[to] = i;if (!vis[to])vis[to] = 1, que.push(to);}}return dis[T] < INF;
}int sap(int &cost)
{int ans = INF;for (int i = T; i != S; i = pre[i]) ans = min(ans, edge[pre_edge[i]].f);for (int i = T; i != S; i = pre[i]) edge[pre_edge[i]].f -= ans, edge[edge[pre_edge[i]].neg].f += ans;cost += ans*dis[T];return ans;
}int mst(int &cost)
{cost = 0;int ans = 0;while (spfa()) ans += sap(cost);return ans;
}int n, m;
int A[30][30], B[30][30], C[30][30];
char str[30];int readln(int A[30][30])
{int cnt = 0;for (int i = 1; i <= n; i++) {scanf("%s", str+1);for (int j = 1; j <= m; j++)A[i][j] = str[j]-'0', cnt += A[i][j];}return cnt;
}inline int number(int i, int j, int id)
{ return (i<=0||i>n||j<=0||j>m)?0:id*n*m+(i-1)*m+j; }int dx[] = {1,0,-1,0, 1, 1, -1, -1}, dy[] = {0,1,0,-1, -1, 1, -1, 1};
int main()
{scanf("%d%d", &n, &m);int a = readln(A);int b = readln(B); readln(C);if (a != b) {puts("-1"); return 0;}for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) {if (A[i][j] == 1) push(S, number(i, j, 0), 1, 0);if (B[i][j] == 1) push(number(i, j, 1), T, 1, 0);if (A[i][j] == 1 && B[i][j] == 1) push(number(i, j, 0), number(i, j, 1), (C[i][j]+2)/2, 1);else if (A[i][j] == 1 || B[i][j] == 1) push(number(i, j, 0), number(i, j, 1), (C[i][j]+1)/2, 1);else push(number(i, j, 0), number(i, j, 1), C[i][j]/2, 1);for (int k = 0; k < 8; k++) push(number(i, j, 1), number(i+dx[k], j+dy[k], 0), INF, 0);}int ans = 0, cost = 0;ans = mst(cost);if (ans == a) {cout << cost-a << endl;} elseputs("-1");return 0;
}

转载于:https://www.cnblogs.com/ljt12138/p/6684333.html

[CQOI2012]交换棋子【网络流】【费用流】相关推荐

  1. P3159 [CQOI2012]交换棋子(费用流)

    题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式:   第 ...

  2. P3159-[CQOI2012]交换棋子【费用流】

    正题 题目链接:https://www.luogu.com.cn/problem/P3159 题目大意 n∗mn*mn∗m的棋盘,每个格子有黑子或白子,每次可以交换两个位置的棋,给出起始态和最终态和每 ...

  3. 【BZOJ-2668】交换棋子 最小费用最大流

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 1055  Solved: 388 [Submit][Stat ...

  4. BZOJ 2668: [cqoi2012]交换棋子

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 1112  Solved: 409 [Submit][Stat ...

  5. 图论-网络流⑦-费用流解题

    图论-网络流⑦-费用流解题 上一篇:图论-网络流⑥-费用流 下一篇:图论-网络流⑧-有上下界的网络流 参考文献: https://www.luogu.com.cn/blog/user9012/solu ...

  6. 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子

    有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...

  7. 修车——网络流——费用流

    这题很明显的是费用流了,关键是在于建图.其实,网络流的关键也是难点就在于建图. n个师傅,m个车-- 根据题意,需要把每个师傅拆成m个点,每辆车再向这些点连接,再来个超级源点S,超级汇点T即可. 代码 ...

  8. P4249 [WC2007]剪刀石头布(网络流/费用流)

    P4249 [WC2007]剪刀石头布 在一个竞赛图上一些边的方向已经确定,但是还有一些边的方向没有确定,求解最多有多少三元环. 首先看到三元环个数,按照套路我们利用度数计算,然后考虑每一条边,每一条 ...

  9. jzoj3302-[集训队互测2013]供电网络【上下界网络流,费用流,动态加边】

    正题 题目大意 若干个城市一些城市有一定的电,有些城市需要一定的电.对于第iii个城市购买一个电需要iniin_iini​,送出电需要outiout_iouti​.当然城市之间也可以相互传输电. 对于 ...

最新文章

  1. Java报错解决:org.apache.http.ConnectionClosedException: Premature end of chunk coded message body: closi
  2. PKI/CA 技术的介绍
  3. 对C语言islower、isupper、isdigit函数的测试
  4. Canvas实现文字粒子化,并且绕轴旋转(完善)
  5. Linux 下的dd命令使用详解(摘录)
  6. EntLib.com Forum / YAF 开源论坛--源码的目录结构(对分析代码很有帮助)
  7. ai 中 统计_AI统计(第2部分)
  8. .NET串口通讯解决方案
  9. Linux环境下源码编译方式安装MySQL5.1(1)
  10. python用均值填充空值_用平均值填充空值
  11. 66个史上最全的行业数据研报网站
  12. NS-miracle安装
  13. c语言OBD编程,汽车OBD2诊断程序开发
  14. python中常用英语口语_1000句常用英语口语
  15. Mencoder安装编译手册
  16. vue-easytable 单元格样式设置
  17. XMind揭秘:汽车的世界
  18. Win10将谷歌浏览器设置为默认浏览器(修改默认应用)
  19. 达芬奇调色软件DaVinci Resolve15破解版
  20. 企业内软件资产管理的必要性

热门文章

  1. 以阿里云RPA为例,来告诉你到底RPA是什么?
  2. 漫谈C#编程语言在游戏领域的应用
  3. mysql密码正确但无法连接【彻底解决方案】
  4. Java扑克牌(多线程)
  5. Oracle 如何修改列的数据类型
  6. k8s command args
  7. CFI Flash, SPI Flash, Nand Flash,Nor Flash的区别和联系
  8. Django框架Day3------之Models
  9. 程序员保值的4个秘密
  10. 使用jquery ajax代替iframe