题目背景
07四川省选
题目描述
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。
每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
输入输出格式
输入格式:
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石柱的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
输出格式:
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
输入输出样例
输入样例#1:
5 8 2 00000000 02000000 00321100 02000000 00000000 ........ ........ ..LLLL.. ........ ........
输出样例#1:
1
说明
100%的数据满足:1<=r, c<=20, 1<=d<=3
题解:网络流
把每个点的权值转移到边上,即拆点,在两个点之间连一条为这个点的权值的边
把所有到这个点的入弧,连到原始点上,把出弧从拆的点发出,这就做到了把点的权值转移到边上
对于每两个能互相跳到的石柱,连权值为INF的边
建源点,汇点
因为每个点只有一只蜥蜴,连一条从源点到这个点权值为1的边 //做的过程中连了权值为INF的边,调了好久。。。
对于每个能令蜥蜴跳出地图的石柱,连一条从这个点到汇点权值为INF的边
跑一遍dinic,蜥蜴个数减最大流即为答案
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int INF=1999999999; int r,c,d;int y=0; int mp1[21][21];bool mp2[21][21];int mp3[21][21]; struct data{ int next,to,cap; }g[200000]; int iter[1000],h[1000],level[1000],k=1,head,tail,q[1000]; void add(int from,int to,int cap) { g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap; g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0; } void bfs(int s) { memset(level,0,sizeof(level)); head=tail=0;q[tail++]=s;level[s]=1; while(head!=tail) { int u=q[head++]; for(int i=h[u];i;i=g[i].next) { if(!level[g[i].to]&&g[i].cap) { level[g[i].to]=level[u]+1;q[tail++]=g[i].to; } } } } int dfs(int u,int t,int f) { if(u==t)return f; int used=0,w; for(int &i=iter[u];i;i=g[i].next) { if(g[i].cap&&level[g[i].to]==level[u]+1) { w=f-used;w=dfs(g[i].to,t,min(w,g[i].cap)); if(w) { g[i].cap-=w;g[i^1].cap+=w;used+=w;if(used==f)return f; } } } return used; } int dinic(int s,int t) { int flow=0; for(;;) { for(int i=1;i<=2*y+2;i++)iter[i]=h[i]; bfs(s);if(!level[t])return flow; flow+=dfs(s,t,INF); } } int main() { int gg=0; scanf("%d%d%d",&r,&c,&d); for(int i=1;i<=r;i++) { char cc[21];scanf("%s",cc); for(int j=1;j<=c;j++)mp1[i][j]=cc[j-1]-'0'; } for(int i=1;i<=r;i++) { char cc[21];scanf("%s",cc); for(int j=1;j<=c;j++) { if(cc[j-1]=='L')mp2[i][j]=1,gg++; else mp2[i][j]=0; } } for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) { if(mp1[i][j])mp3[i][j]=++y; } for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) { for(int k1=1;k1<=r;k1++) for(int k2=1;k2<=c;k2++) { if(k1==i&&k2==j)continue; if((k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j]&&mp1[k1][k2]) {add(mp3[i][j]+y,mp3[k1][k2],INF);add(mp3[k1][k2]+y,mp3[i][j],INF);} } if(mp1[i][j])add(mp3[i][j],mp3[i][j]+y,mp1[i][j]); if(mp2[i][j])add(2*y+1,mp3[i][j],1); for(int k1=0;k1<=r+1;k1++) for(int k2=0;k2<=c+1;k2++) { if((k1==0||k1==r+1||k2==0||k2==c+1)&&(k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j]) {add(mp3[i][j]+y,2*y+2,INF);} } } cout<<gg-dinic(2*y+1,2*y+2); return 0; }