AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1066
蜥蜴
Description
在一个
r
行
你的任务是让尽量多的蜥蜴逃到边界外。
每行每列中相邻石柱的距离为
1
,蜥蜴的跳跃距离是
石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减
如果该石柱原来高度为
1
,则蜥蜴离开后消失,以后其他蜥蜴不能落脚。
任何时刻不能有两只蜥蜴在同一个石柱上。
Input
输入第一行为三个整数
以下
r
行为石竹的初始状态,
以下
r
行为蜥蜴位置,“
Sample Input
5 8 2
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..
Sample Output
1
HINT
友情提示:题干中的距离指的是曼哈顿距离(我因为这个WA了一次)。
Solution
这道题我的思路是这样的:
因为对于任意一个有高度的石柱,只能有不超过一定数量的蜥蜴跳到它的上面,所以我们可以把这个“跳跃”的动作看作一个“流”,而所有流的流量之和不能超过这个石柱的高度。
所以我们可以设置一个虚点:将“跳到它之上”的流全部汇集到这个虚点上,再从虚点流到这个石柱上,设置流量的限制。
这样就
Code
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #define Min(a,b) ((a)<(b)?(a):(b))
- #define abs(a) ((a)>0?(a):(-(a)))
- using namespace std;
- char s1[100][100];
- char s2[100][100];
- int r,c,d,s,t,cnt,tot;
- const int INF=0x3f3f3f3f;
- const int END=20*20+20*20+21*21;
- const int START=20*20+20*20+20*20;
- const int MAXN=100000;
- int data[MAXN*2],low[MAXN*2];
- int nxt[MAXN*2],head[MAXN];
- int dis[MAXN];
- queue<int>q;
- void add(int x,int y,int z){
- nxt[cnt]=head[x];data[cnt]=y;low[cnt]=z;head[x]=cnt++;
- nxt[cnt]=head[y];data[cnt]=x;low[cnt]=0;head[y]=cnt++;
- }
- bool BFS(){
- memset(dis,-1,sizeof dis);
- dis[s]=0;
- q.push(s);
- while(!q.empty()){
- int now=q.front();
- q.pop();
- for(int i=head[now];i!=-1;i=nxt[i])
- if(low[i]&&dis[data[i]]<0){
- dis[data[i]]=dis[now]+1;
- q.push(data[i]);
- }
- }
- return dis[t]>0;
- }
- int dfs(int now,int flow){
- if(now==t)return flow;
- int Low;
- for(int i=head[now];i!=-1;i=nxt[i]){
- if(low[i]&&dis[data[i]]==dis[now]+1){
- if(Low=dfs(data[i],Min(flow,low[i]))){
- low[i]-=Low;
- low[i^1]+=Low;
- return Low;
- }
- }
- }
- return 0;
- }
- int main(){
- memset(head,-1,sizeof head);
- scanf(”%d%d%d”,&r,&c,&d);
- for(int i=1;i<=r;i++)scanf(“%s”,s1[i]);
- for(int i=1;i<=r;i++)scanf(“%s”,s2[i]);
- for(int i=1;i<=r;i++)
- for(int j=0;j<c;j++)if(s1[i][j]!=‘0’)
- for(int k=1;k<=r;k++)
- for(int l=0;l<c;l++)if(s1[k][l]!=‘0’&&(i!=k||j!=l))
- if(abs(i-k)+abs(j-l)<=d)
- add(i*c+j,(k*c+l)+r*c+r*c,INF);
- for(int i=1;i<=r;i++)
- for(int j=0;j<c;j++)if(s1[i][j]!=‘0’)add((i*c+j)+r*c+r*c,i*c+j,s1[i][j]-‘0’);
- for(int i=1;i<=r;i++)
- for(int j=0;j<c;j++)
- if(s2[i][j]==‘L’){
- add(START,(i*c+j)+r*c+r*c,1);
- tot++;
- }
- for(int i=1;i<=r;i++)
- for(int j=0;j<c;j++)
- if(s1[i][j]!=‘0’&&((i<=d||(r-i+1)<=d)||(j+1<=d||(c-j<=d)))){
- add(i*c+j,END,tot);
- }
- s=START;
- t=END;
- int sum=0;
- while(BFS()){
- int flow=0;
- while(flow=dfs(s,INF))sum+=flow;
- }
- printf(”%d\n”,tot-sum);
- return 0;
- }