bzoj2668
对于这种题很容易看出是费用流吧……
但这道题不容易建模;
首先是怎么表示目标状态和其实状态,看起来有黑有白很复杂
但实际上,不难发现,白色格子没什么用,起决定作用的是黑格子
也就是我们可以把问题简化:我们怎么把开始的黑格子移到目标位置
但这个移动不是一般的移动;
在一条路径中,不难发现,起始两点是只要交换一次,其他路径上个点都是要交换2次
由于题目给出的限制是点的交换次数限制c,所以不难想到要拆点
但是平常的拆两点好像无法表示这个特征,
于是我们就拆成3个点……
p1--->p0--->p2
p1表示交换进来,p2表示交换出去;
所以不难得出:
对于每个点,如果它是原图中的黑点,连边<p1,p0,c/2,0>,<p0,p2,(c+1)/2,0>,<s,p0,1,0>;
如果它是新图中的黑点,连边<p1,p0,(c+1)/2>,<p0,p2,c/2,0>,<p0,t,1,0>;
注意存在有的点在新图原图都是黑点的情况(在这里WA了一次)
如果它在两个图中都是白点,那么连边<p1,p0,c/2,0>,<p0,p2,c/2,0>
最后对于原图中任意可达两点,连边<pi2,pj1,inf,1>
注意这道题可以交换对角线,还要判断是否可行,细节挺多
const dx:array[..] of integer=(-,,,,,-,-,);
dy:array[..] of integer=(,,,-,,-,,-);
inf=;
type node=record
next,point,cost,flow:longint;
end; var edge:array[..] of node;
p,pre,cur,d:array[..] of longint;
v:array[..] of boolean;
a,b,c:array[..,..] of integer;
q:array[..] of longint;
ch,t,n,m,i,j,k,x,y,po,tot,sum,ans,len:longint;
s:string; procedure add(x,y,f,w:longint);
begin
inc(len);
edge[len].point:=y;
edge[len].flow:=f;
edge[len].cost:=w;
edge[len].next:=p[x];
p[x]:=len;
end; function spfa:boolean;
var i,x,y,f,r:longint;
begin
fillchar(v,sizeof(v),false);
v[]:=true;
for i:= to t do
d[i]:=inf;
d[]:=;
f:=;
r:=;
q[f]:=;
while f<=r do
begin
x:=q[f];
v[x]:=false;
i:=p[x];
while i<>- do
begin
y:=edge[i].point;
if edge[i].flow> then
if d[y]>d[x]+edge[i].cost then
begin
d[y]:=d[x]+edge[i].cost;
pre[y]:=x;
cur[y]:=i;
if not v[y] then
begin
inc(r);
q[r]:=y;
v[y]:=true;
end;
end;
i:=edge[i].next;
end;
inc(f);
end;
if d[t]=inf then exit(false) else exit(true);
end; procedure mincost;
var i,j,neck:longint;
begin
while spfa do
begin
i:=t;
neck:=inf;
while i<> do
begin
j:=cur[i];
if neck>edge[j].flow then neck:=edge[j].flow;
i:=pre[i];
end;
i:=t;
while i<> do
begin
j:=cur[i];
dec(edge[j].flow,neck);
inc(edge[j xor ].flow,neck);
i:=pre[i];
end;
ans:=ans+d[t]*neck;
dec(ch,neck);
if ch= then break;
end;
end; begin
readln(n,m);
len:=-;
fillchar(p,sizeof(p),);
t:=*n*m+;
for i:= to n do
begin
readln(s);
for j:= to m do
begin
a[i,j]:=ord(s[j])-;
tot:=tot+a[i,j];
end;
end;
for i:= to n do
begin
readln(s);
for j:= to m do
begin
b[i,j]:=ord(s[j])-;
sum:=sum+b[i,j];
end;
end;
for i:= to n do
begin
readln(s);
for j:= to m do
c[i,j]:=ord(s[j])-;
end;
if sum<>tot then
begin
writeln(-);
halt;
end
else ch:=sum;
sum:=n*m;
for i:= to n do
begin
for j:= to m do
begin
x:=(i-)*m+j;
if a[i,j]= then
begin
add(x+sum,x,c[i,j] shr ,);
add(x,x+sum,,);
add(x,x+*sum,(c[i,j]+) shr ,);
add(x+*sum,x,,);
add(,x,,);
add(x,,,);
if b[i,j]= then //细节
begin
add(x,t,,);
add(t,x,,);
end;
end
else if b[i,j]= then
begin
add(x+sum,x,(c[i,j]+) shr ,);
add(x,x+sum,,);
add(x,x+*sum,c[i,j] shr ,);
add(x+*sum,x,,);
add(x,t,,);
add(t,x,,);
end
else if (a[i,j]+b[i,j]=) then
begin
add(x+sum,x,c[i,j] shr ,);
add(x,x+sum,,);
add(x,x+*sum,c[i,j] shr ,);
add(x+*sum,x,,);
end;
end;
end; for i:= to n do
for j:= to m do
begin
po:=(i-)*m+j;
for k:= to do
begin
x:=i+dx[k];
y:=j+dy[k];
if (x<=n) and (y<=m) and (x>) and (y>) then
begin
tot:=(x-)*m+y;
add(po+*sum,tot+sum,inf,);
add(tot+sum,po+*sum,,-);
end;
end;
end;
mincost;
if ch<> then writeln(-) else writeln(ans);
end.
bzoj2668的更多相关文章
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- BZOJ2668 [cqoi2012]交换棋子 【费用流】
题目链接 BZOJ2668 题解 容易想到由\(S\)向初始的黑点连边,由终态的黑点向\(T\)连边,然后相邻的点间连边 但是这样满足不了交换次数的限制,也无法计算答案 考虑如何满足一个点的交换次数限 ...
- 【BZOJ-2668】交换棋子 最小费用最大流
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1055 Solved: 388[Submit][Status ...
- BZOJ2668: [cqoi2012]交换棋子
题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...
- BZOJ2668:[CQOI2012]交换棋子——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2668 https://www.luogu.org/problemnew/show/P3159#sub ...
- BZOJ2668:[CQOI2012]交换棋子(费用流)
题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...
- [CQOI2012][bzoj2668] 交换棋子 [费用流]
题面 传送门 思路 抖机灵 一开始看到这题我以为是棋盘模型-_-|| 然而现实是骨感的 后来我尝试使用插头dp来交换,然后又惨死 最后我不得不把目光转向那个总能化腐朽为神奇的算法:网络流 思维 我们要 ...
- BZOJ2668: [cqoi2012]交换棋子(费用流)
Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...
- [bzoj2668] [洛谷P3159] [cqoi2012] 交换棋子
Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...
随机推荐
- 手机淘宝用JS来动态写meta标签(1像素边框处理方法)
var metaEl = doc.createElement('meta'); var scale = isRetina ? 0.5:1; metaEl.setAttribute('name', 'v ...
- Perl中的特殊内置变量详解
#!/usr/bin/perl -w @array = qw(a b c d); foreach (@array) { print $_," "; } 例子的作用就是定义一个数组并 ...
- Mac环境下装node.js,npm,express;(包括express command not found)
1. 下载node.js for Mac 地址: http://nodejs.org/download/ 直接下载 pkg的,双击安装,一路点next,很容易就搞定了. 安装完会提醒注意 node和n ...
- SQLSERVER数据库管理数据库原理
数据库的存储结构: 1.逻辑存储结构:是指数据库有那些性质的信息组成,即一个数据库由若干用户可视的各种数据库对象构成,如:表,视图,索引,存储过程等 2.物理存储结构:表现为存储数据的各类操作系 ...
- java程序练习:猜字母
猜字母程序=数据结构+算法 首先:定义数据结构1.找名词Input:输入变量Output:输出变量隐含:找到隐含的变量,如字符串 其次:定义算法,程序的处理 最后:按照顺序,逐步实现 注意:1.基本数 ...
- MyISAM读写并发优化
MyISAM在读操作占主导的情况下是很高效的.可一旦出现大量的读写并发,同InnoDB相比,MyISAM的效率就会直线下降,而 且,MyISAM和InnoDB的数据存储方式也有显著不同:通常,在MyI ...
- Extjs4.2布局——Ext.container.ViewportView
先贴出官方文档的关于此布局的描述:“ 一个专门的容器用于可视应用领域(浏览器窗口). Viewport渲染自身到网页的documet body区域, 并自动将自己调整到适合浏览器窗口的大小,在窗口大小 ...
- Partition an array around an interger
Partition an array of integers around a value such taht all elements less than x come before element ...
- uva 10069
简单的dp 但是一个大数加法 套用了末位大牛的类模板 #include <cstdio> #include <cstring> #include <algorithm& ...
- shuffle过程中的信息传递
依据Spark1.4版 Spark中的shuffle大概是这么个过程:map端把map输出写成本地文件,reduce端去读取这些文件,然后执行reduce操作. 那么,问题来了: reducer是怎么 ...