[Bzoj 2547] [Ctsc2002] 玩具兵
2547: [Ctsc2002]玩具兵
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 317 Solved: 152
[Submit][Status][Discuss]
Description
小明的爸爸给他买了一盒玩具兵,其中有 K个步兵,K个骑兵和一个天兵,个个高大威猛,形象逼真。盒子里还有一个M*N棋盘,每个格子(i,j)都有一个高度Hij,并且大得足以容纳所有的玩具兵。小明把所有的玩具兵都放到棋盘上去,突然想到了一种很有趣的玩法:任意挑选T个不同的格子,并给每个格子i规定一个重要值Ri,游戏的目标就是每次沿东南西北之一的方向把一个玩具兵移动到其相邻的格子中(但不能移动到棋盘外面去),最终使得每个挑选出的格子i上恰好有Ri个玩具兵。小明希望所有的玩具兵都在某个选定的格子中,因此他总是使选出的T个格子的重要值之和等于玩具兵的个数。为了增加难度,小明给玩具兵们的移动方式做了一些规定:
- 步兵只会往高处爬,因此如果两个格子A和B相邻,当且仅当格子A的高度小于或等于B,步兵才可以从A移动到B。
- 骑兵只会往低处跳,因此如果两个格子A和B相邻,当且仅当格子A的高度大于或等于B,骑兵才可以从A移动到B。
- 天兵技术全面,移动不受任何限制。
可是没玩几次,小明就发现这个游戏太难了,他常常玩了好半天也达不到目的。于是,他设计了一种“超能力”,每使用一次超能力的时候,虽然不能移动任何一个玩具兵,但可对它们进行任意多次交换操作,每次交换两个玩具兵。等这次超能力使用完后又可和平常一样继续移动这些玩具兵。借助强大的超能力,这个游戏是容易玩通的,但是怎样才能让使用超能力的次数最少呢?
Input
第一行包含四个整数:M,N,K,T (2<=M,N<=100, 1<=K<=50, 1<=T<=2K+1)
第二行包括2K+1个数对(xi,yi),代表各个玩具兵的初始位置。前K个代表步兵,接下来的K个代表骑兵,最后一个代表天兵。
第三行包含T个三元组(xi,yi,ri),第i组代表第i个目标格的位置和重要值。
以下M行,每行N个整数。其中第i行第j个数为即格子的高度Hij。高度是不超过100的正整数,注意:不同玩具兵的初始位置可能相同。输入数据保证无错,选定的T个格子的重要值之和保证等于2K+1。
Output
仅包含一行,即使用超能力的最小次数T。
Solution
观察到每次交换可以换无数次,所以每次一定是把步兵和骑兵换一下,相当于每个都走到无路可走的地方,然后换个职业继续走。
所以对于每个玩具兵(先不考虑天兵),都 Spfa 瞎搞出到每个点最少要交换的次数,也就是说,至少要交换 _dis[i][j] 次才能到达 (i,j)。
然后二分答案,二分出交换的次数 mid,然后对于每个玩具兵,向交换次数小于 mid 的终点连边,然后跑最大流即可。
注意最后要加上二分出的 mid,意义就是天兵每次都可以替代一个玩具兵走到终点,然后换它们俩就好。
Code
// By YoungNeal
#include<queue>
#include<cstdio>
#include<cstring>
];
int s,t,maxflow;
];
][];
][];
][]; // 记录交换了几次 dis[i][j]->第i个兵到第j个目标
int m,n,k,T,ans,cnt;
][];
][][]; // _dis[i][j]->从当前的点到(i,j)最少交换次数
][][]; // in[i][j][p]->当前点到(i,j)职业为p是否在队列
,,,},dy[]={,,,-};
struct Node{
int x,y,o;
};
struct Edge{
int to,nxt,flow;
}edge[];
void add(int x,int y,int z){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].flow=z;
head[x]=cnt;
}
void spfa(int now,int xx,int yy,int cnt){
std::queue<Node> q;
memset(,sizeof in);
memset(_dis,0x3f,sizeof _dis);
_dis[xx][yy][cnt]=;
q.push((Node){xx,yy,cnt});
while(q.size()){
int x=q.front().x;
int y=q.front().y;
int o=q.front().o;
q.pop(); ;
;k<;k++){
int nx=x+dx[k];
int ny=y+dy[k];
int nowdis,oo;
||nx>m||ny<||ny>n) continue;
&&height[nx][ny]>=height[x][y])||(o==&&height[nx][ny]<=height[x][y]))
nowdis=_dis[x][y][o],oo=o;
,oo=o^;
if(_dis[nx][ny][oo]>nowdis){
_dis[nx][ny][oo]=nowdis;
,q.push((Node){nx,ny,oo});
}
}
}
;i<=T;i++){
dis[now][i]=std::min(_dis[goal[i][]][goal[i][]][],_dis[goal[i][]][goal[i][]][]);
}
}
void clear(){
maxflow=;
cnt=;s=k*+T+;t=s+;
memset(edge,,sizeof edge);
memset(head,,sizeof head);
}
bool bfs(){
std::queue<int> q;
memset(d,,sizeof d);
q.push(s);d[s]=;
while(q.size()){
int u=q.front();q.pop();
for(int i=head[u];i;i=edge[i].nxt){
int to=edge[i].to;
if(d[to]) continue;
if(!edge[i].flow) continue;
d[to]=d[u]+;
q.push(to);
;
}
}
;
}
int dinic(int now,int flow){
if(now==t) return flow;
int rest=flow,k;
for(int i=head[now];i;i=edge[i].nxt){
if(!rest) return flow;
int to=edge[i].to;
if(!edge[i].flow) continue;
) continue;
k=dinic(to,std::min(rest,edge[i].flow));
;
edge[i].flow-=k;
edge[i^].flow+=k;
rest-=k;
}
return flow-rest;
}
bool check(int mid){
clear();
;i<=k*;i++){
;j<=T;j++){
,),add(j+k*,i,);
}
}
;i<=k*;i++) add(s,i,),add(i,s,);
;i<=T;i++) add(i+k*,t,goal[i][]),add(t,i+k*,);
;
while(bfs()) while(flow=dinic(s,0x3f3f3f3f)) maxflow+=flow;
;
}
signed main(){
scanf("%d%d%d%d",&m,&n,&k,&T);
;i<=k*+;i++) scanf(],&toy[i][]);
;i<=T;i++) scanf(],&goal[i][],&goal[i][]);
;i<=m;i++){
;j<=n;j++) scanf("%d",&height[i][j]);
}
;i<=(k<<);i++) spfa(i,toy[i][],toy[i][],(i>k));
,r=(k<<)+;
while(l<=r){
;
;
;
}
printf("%d\n",ans);
;
}
[Bzoj 2547] [Ctsc2002] 玩具兵的更多相关文章
- BZOJ 2547: [Ctsc2002]玩具兵(二分答案+二分图匹配)
传送门 解题思路 可以发现天兵不用管,答案的一个上界是\(2*k\),就是天兵一个个换.刚开始写了个拆\(6\)点的网络流,调了半天发现自己假了..说说正解,首先可以发现交换士兵其实就是种类的交换,那 ...
- BZOJ2547 CTSC2002玩具兵(最短路径+二分答案+最大流)
先不考虑只有一个显得有些特殊的天兵. 可以发现超能力的作用实质上是使兵更换职业.每一个兵到达某个位置最少需要更换职业的次数是彼此独立的,因为如果需要某两人互换职业可以使他们各自以当前职业到达需要到的地 ...
- bzoj2547: [Ctsc2002]玩具兵
划了一天水,其实我还是有点愧疚的. 传送门 其实是水题,然而我真是太蠢了... 首先不考虑天兵,其他兵要到一个点去一定是通过它-另一种兵-它……这样多次交换的,并且交换对象是无所谓的,和它换的兵最终会 ...
- [BZOJ 2547] 玩具兵
Link: BZOJ 2547 传送门 Solution: 很容易通过解可行性的单调性想到二分答案,接下来考虑如何验证解 发现一个很奇妙的条件:步兵和骑兵的个数相同 因此交换位置时不用考虑可行性,保证 ...
- Bzoj 1055: [HAOI2008]玩具取名 (区间DP)
Bzoj 1055: [HAOI2008]玩具取名 (区间DP) 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1055 区间动态规划和可 ...
- [bzoj2547]玩具兵<Spfa+二分+匈牙利算法>
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2547 挺有意思的一道题,这道题可以划分成几个小题....... 题目大意: 三个兵种在一个 ...
- BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9812 Solved: 3978[Submit][St ...
- BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP
1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...
- bzoj 1054 移动玩具
题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1054 移动玩具 Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想 ...
随机推荐
- 关于Maven的web项目的创建
网上关于Maven的web项目创建多种多样,先本人在研究Maven之余,创建一套自己试过并有效的创建步骤. 1.点击右键>选择Maven Project,如下图所示: 2.点击创建,如下图所示: ...
- linux下FFmpeg编译生成ffplay
1.确认Makefile中指定的config.mak(在ffmpeg根目录下)中:CONFIG_FFPLAY=yes,如果不是需要重新./configure 该处还有ffmpeg.ffprobe.ff ...
- R语言︱函数使用技巧(循环、if族/for、switch、repeat、ifelse、stopifnot)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 后续加更内容: 应用一:if族有哪些成员呢?- ...
- dojo表格分页插件报错
dojo表格分页插件报错 (1)dojo/parser::parse() error ReferenceError {stack:(...),message:"layout is not d ...
- Error: expected expression, got '}'
1.错误描述 Error: expected expression, got '}' .globalEval/<@http://localhost:8080/Sys/resource/globa ...
- Caused by: java.lang.ClassNotFoundException: org.springframework.expression.ExpressionParser
1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...
- box-sizing -- 盒模型
项目开发中,在浏览同事的代码,发现他经常用一个属性--box-sizing,很好奇是什么,于是乎,上网查阅资料学了起来. 首先我们先复习一下盒模型的组成:一个div通常由 content(内容)+ma ...
- 利用scrapy模拟登录知乎
闲来无事,写一个模拟登录知乎的小demo. 分析网页发现:登录需要的手机号,密码,_xsrf参数,验证码 实现思路: 1.获取验证码 2.获取_xsrf 参数 3.携带参数,请求登录 验证码url : ...
- js中的0就是false,非0就是true及案例
在处理js代码判断真假时经常会这么写. 但fun()可能得到的是数字0,这可不是表示的没有值,但是!js中的数字0就是false,非0就是true. 于是0就被无情的当做false了. 已经被这个坑过 ...
- div里面的图片垂直居中
外面一个div, 里面是一张大小不固定的图片, 或者span,div都行, 要实现里面元素水平垂直居中对齐 其实有很多实现的方法, 比如用js去计算每一个子元素的高度, 通过js去动态设置magin值 ...