[bzoj2547]玩具兵<Spfa+二分+匈牙利算法>
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2547
挺有意思的一道题,这道题可以划分成几个小题。。。。。。。
题目大意:
三个兵种在一个n*m的图上,图的每一个格子有一个高度,三个兵种一种走不下降的路,一种走不上升的路,一种随便走。数量分别是k,k,1
然后t个目的地,每个目的地必须有ri个兵,ri之和为2*k+1
然后你可以交换兵,让不能走的情况又变成能走,例如,第一种兵走到了山顶,四周都是下降的,这时候就可以和第二,三种兵交换位置,继续走下去。。。
【解题思路】
这道题分解下来就是先来一个spfa找每一个兵到每一个点的最小交换次数,然后就是二分这个一共的交换次数,接着就是二分图匹配。。。
我们跑spfa,以每个兵开始扩展,遇到不能走就换一次,记录每个兵到每个点的最小交换次数,然后把当前兵到指定点的值记录入一个新的数组(表示二分图的连接情况)
然后二分。。因为最少是不交换,最大交换2*k次,因为可以每个兵和天兵交换一次然后去终点,天兵是随便走,所以最多交换2*k次,然后二分次数。。二分当中的check就是用二分图匹配了。。。Check成立的判断时交换次数+最大匹配数,如果这个值大于了兵的数量,说明这个方案是可行的。。。
这是大致思路,但是还是要注意一些细节的地方。
Spfa要注意当前的兵种是在变化的,所以要结合到当前位置之前的交换次数和最初状态
最初为0,交换偶数次,当前还是0,交换奇数次,当前为1
最初为1,交换偶数次,当前还是1,交换奇数次,当前为0
假设开始是c,次数是t,这个最终结果就是c^(t&1)
另外一个就是要注意二分图匹配时,除了要求vis[i]==0之外,还有x兵到i点的次数小于我们二分出来的限制。。。
然后就还是结合代码理解吧,我看别人的思路都不是很懂,还是结合代码读懂的。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<queue>
#define maxn 105
using namespace std; const int dx[]={,-,,,};
const int dy[]={,,,-,}; int att[maxn][maxn],h[maxn][maxn];
int f[maxn][maxn];//表示到达这个位置的最小交换次数
int n,m,k,t,r;
pair<int,int>a[maxn];
pair<int,int>b[maxn];
queue<pair<int,int> >q; void init()
{
scanf("%d%d%d%d",&n,&m,&k,&t);
for(int i=;i<=*k+;i++)
{
scanf("%d%d",&a[i].first,&a[i].second);
}
int tot=;
for(int i=;i<=t;i++)
{
scanf("%d%d%d",&b[tot].first,&b[tot].second,&r);
r--;tot++;
for(r;r>=;r--,tot++){
b[tot]=b[tot-];
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&h[i][j]);
} void bfs(int x,int y,int cnt){
memset(f,0x3f3f3f,sizeof(f));
f[x][y]=;
q.push(make_pair(x,y));
while(!q.empty()){
int nx=q.front().first,ny=q.front().second;
for(int i=;i<=;i++)
{
int nowx=nx+dx[i],nowy=ny+dy[i];
if(nowx<||nowx>n||nowy<||nowy>m)continue;
int tt=;
if(cnt^(f[nx][ny]&)){
if(h[nowx][nowy]>h[nx][ny])tt=;
}else if(h[nowx][nowy]<h[nx][ny])tt=;
if(f[nowx][nowy]>f[nx][ny]+tt){
f[nowx][nowy]=f[nx][ny]+tt;
q.push(make_pair(nowx,nowy));
} }
q.pop();
} } int vis[maxn*],ck[maxn*]; int ok(int x,int limit){
for(int i=;i<=*k+;i++)
{
if(vis[i]==&&att[x][i]<=limit){
vis[i]=;
if(ck[i]==||ok(ck[i],limit)){
ck[i]=x;return ;
}
}
}
return ;
} int check(int x){
memset(ck,,sizeof(ck));
int tot=;
for(int i=;i<=*k;i++){
memset(vis,,sizeof(vis));
if(ok(i,x))tot++;
}
if(tot+x>=*k)return ;
else return ;
} int ans(){
int l=,r=*k;//最坏情况就是天兵挨着和每一个交换,最多换2*k次
while(l<r){
int mid=(l+r)>>;
if(check(mid))r=mid;else l=mid+;
}
return l;
} int main()
{
init();
for(int i=;i<=*k;i++)
{
if(i<=k)bfs(a[i].first,a[i].second,);
else bfs(a[i].first,a[i].second,);
for(int j=;j<=*k+;j++){
att[i][j]=f[b[j].first][b[j].second];
}
}
printf("%d\n",ans());
}
总结:
把一个大题打乱成多个小题是一个很有效的方式
注意分析状态的变化,比如题中的兵种在spfa的时候是变化的
[bzoj2547]玩具兵<Spfa+二分+匈牙利算法>的更多相关文章
- [ACM_图论] The Perfect Stall 完美的牛栏(匈牙利算法、最大二分匹配)
描述 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术.不幸的是,由于工程问题,每个牛栏都不一样.第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们 ...
- hdu 2444 The Accomodation of Students(二分匹配 匈牙利算法 邻接表实现)
The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...
- 51 NOd 2006 飞行员配对(匈牙利算法二分匹配)
题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一 ...
- 匈牙利算法模板 hdu 1150 Machine Schedule(二分匹配)
二分图:https://blog.csdn.net/c20180630/article/details/70175814 https://blog.csdn.net/flynn_curry/artic ...
- hdu2063 最大二分匹配(匈牙利算法)
过山车 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 【01染色法判断二分匹配+匈牙利算法求最大匹配】HDU The Accomodation of Students
http://acm.hdu.edu.cn/showproblem.php?pid=2444 [DFS染色] #include<iostream> #include<cstdio&g ...
- [Bzoj 2547] [Ctsc2002] 玩具兵
2547: [Ctsc2002]玩具兵 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 317 Solved: 152[Submit][Status] ...
- HDU5090——Game with Pearls(匈牙利算法|贪心)(2014上海邀请赛重现)
Game with Pearls Problem DescriptionTom and Jerry are playing a game with tubes and pearls. The rule ...
- Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)
解题报告 二分图第一题. 题目描写叙述: 为了參加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; ...
随机推荐
- 7-34 jmu-python-是否偶数 (10 分)
输入一个整数,判断是否偶数 输入样例: 7 输出样例: 7不是偶数 输入样例: 8 输出样例: 8是偶数 a = int(input()) if (a % 2 == 0): print('%d是偶数' ...
- js实现文字头像的生成
原文地址:https://www.phyer.cn/article/9277.欢迎大家访问我的博客(●ˇ∀ˇ●) 使用canvas画出文字就好啦 function gen_text_img(size, ...
- VUE实现Studio管理后台(九):开关(Switch)控件,输入框input系列
接下来几篇作文,会介绍用到的输入框系列,今天会介绍组普通的调用方式,因为RXEditor要求复杂的输入功能,后面的例子会用VUE的component动态调用,就没有今天的这么直观了,控件的实现原理都一 ...
- iview中select搜索
https://www.jianshu.com/p/1c40d7cc440e https://www.cnblogs.com/yun1108/p/10967735.html https://blog. ...
- Flink系列之状态及检查点
Flink不同于其他实时计算的框架之处是它可以提供针对不同的状态进行编程和计算.本篇文章的主要思路如下,大家可以选择性阅读. 1. Flink的状态分类及不同点. 2. Flink针对不同的状态进行编 ...
- Oracle - 坏块修复(一)
一.概述 本文将介绍如何模拟坏块,以及出现坏块该如何修复.实验分为以下几个步骤. 1. 表出现坏块 2. 索引出现坏块 二.环境准备 本实验都是在oracle 11G归档模式下进行. 1. 准备相关表 ...
- Logback,SLF4J,Log4J2。了解它们并学习如何使用。(翻译)
背景 如果您正在或在任何Java项目上工作,则可能已记录了一些debug,error或info语句以进行调试或跟踪.通过将库记录到磁盘或其他某种介质上的文件中来写这些语句. 日志记录是任何项目的关键方 ...
- Intel优化Gen7驱动代码 Geekbench 5性能猛增
Linux下缺少大量开发.支持是会导致各种奇葩的错误的,Intel日前就提交了一个代码修复,22nm Ivybridge及Haswell处理器的GeekBench 5的性能就提升了330%. 3.3倍 ...
- 开源项目在闲鱼、b 站上被倒卖?这是什么骚操作?
起因 - 又是一封邮件 2020 年 3 月 2 日,收到了一封邮件,对,这次故事的起因又是一封邮件,和上次写个bug被国家信息安全漏洞共享平台抓到了一样. 这是一条评论通知邮件,一开始我以为只是正常 ...
- R语言实战(二) 创建数据集
2.1 数据集的概念 不同的行业对于数据集的行和列叫法不同.统计学家称它们为观测(observation)和变量(variable),数据库分析师则称其为记录(record)和字段(field),数据 ...