[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的方框内摆放了若干个相同的玩具,某人想 ...
随机推荐
- node实现jsonp跨域
1. 搭建node server //引入模块 var http=require("http"); var fs=require("fs");var url = ...
- jmeter压力测试笔记- HTTP协议
一.目标 使用jmeter进行HTTP接口压力测试: 命令行方式运行,方便在linux环境运行: 二.面临的问题 支持多环境测试(开发.测试.生产环境) 支持用户数据.线程数.循环次数等配置在运行时自 ...
- mxnet:结合R与GPU加速深度学习
转载于统计之都,http://cos.name/tag/dmlc/,作者陈天奇 ------------------------------------------------------------ ...
- Caused by: java.io.FileNotFoundException
1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...
- pat1051-1060
1051 自己写的非常麻烦 http://blog.csdn.net/biaobiaoqi/article/details/9338397 的算法比较好,我的就贴下吧,主要对入栈出栈不够理解 #inc ...
- Mysql简单笔记
对oracle还是比较熟悉的,对mysql也是零散的有些了解,今天看了下,简单总结: 1.查看mysql版本:mysqladmin --version2.查看mysql进程:ps -ef|grep m ...
- Asp.Net WebApi 调试利器“单元测试”
当我们编辑好一个WebApi应用程序后,需要对该Api接口进行调试,传统的调试办法是在方法内设置断点,然后用PostMan等http工具模拟访问进行查看WebAPI的运行情况,但这种除了效率较低还进行 ...
- C#读取Excel表格中数据并返回datatable
在软件开发的过程中,经常用到从excel表格中读取数据作为数据源,以下整理了一个有效的读取excel表格的方法. DataTable GetDataTable(string tableName,str ...
- 畅通工程 HDU - 1863
省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出了有可能建设公路的若干条道 ...
- RobotFramework下的http接口自动化Set Request Body 关键字的使用
Set Request Body关键字用来设置http 请求时的body 信息,尤其是在post 请求时,经常需要用到这个关键字. 该关键字接收一个参数,[ body ] 示例1:登录博客园(http ...