BZOJ 1066 [SCOI2007]蜥蜴
1066: [SCOI2007]蜥蜴
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2356 Solved: 1148
[Submit][Status][Discuss]
Description
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
Input
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
Output
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
Sample Input
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
1
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
Source
题解:一道有意思的网络流哦。以前的建模都是针对问题本身,这次的建模却是针对网络流本身啊。。。。
可以考虑一下:当一只蜥蜴跳走的时候,所在的木桩减一,那么窝萌是不是就可以把每一个木桩想成是一条边呢?每一只蜥蜴的选择就是流量,过一只蜥蜴流量加一,其实就是在残量网络中容量减一,完全符合网络流,不错哦。。。
然后该怎么建图就怎么建图。
这道题窝WA了好几发,分享一下错误。。。
1.找了好半天的最严重的错误:
int id1(int x,int y){return (x-1)*m+y;}int id2(int x,int y){return (x-1)*m+y+sizn;}
x的下标从1开始,那么x不减一就死咯。。。
2.忘记这不是正方形了,就把c忽视了。。。。
3.判断跳出的in方法中没想清楚加不加等号
4.一个tip,最开始用的是欧几里得距离,带着double和eps算的,以后还是要尽量避免浮点运算。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<stack> 6 #include<queue> 7 #include<cstring> 8 #define PAU putchar(' ') 9 #define ENT putchar('\n') 10 #define MSE(a,b) memset(a,b,sizeof(a)) 11 #define REN(x) for(ted*e=fch[x];e;e=e->nxt) 12 #define TIL(x) for(int i=1;i<=x;i++) 13 #define ALL(x) for(int j=1;j<=x;j++) 14 using namespace std; 15 const int maxt=20+5,maxn=800+10,maxm=320000+10,inf=-1u>>1; 16 int n,m,d,map[maxt][maxt];bool b[maxt][maxt];char s[maxt]; 17 struct isap{ 18 struct ted{int x,y,w;ted*nxt,*re;}adj[maxm],*fch[maxn],*cur[maxn],*ms; 19 int d[maxn],gap[maxn],ret[maxn],S,T,n; 20 void init(int n){this->n=n;ms=adj;MSE(d,-1);return;} 21 void add(int x,int y,int w){ 22 *ms=(ted){x,y,w,fch[x],ms+1};fch[x]=ms++; 23 *ms=(ted){y,x,0,fch[y],ms-1};fch[y]=ms++; 24 return; 25 } 26 void bfs(){ 27 queue<int>Q;Q.push(T);d[T]=0; 28 while(!Q.empty()){ 29 int x=Q.front();Q.pop();REN(x){int v=e->y; 30 if(d[v]<0)d[v]=d[x]+1,Q.push(v); 31 } 32 }return; 33 } 34 int mxflow(int S,int T){ 35 this->S=S;this->T=T;bfs();int flow=0,k=S;ted*e;TIL(n)gap[d[i]]++,cur[i]=fch[i]; 36 while(d[S]<n){ 37 if(k==T){int mi=inf,p; 38 for(int i=S;i!=T;i=cur[i]->y)if(cur[i]->w&&cur[i]->w<mi)mi=cur[i]->w,p=i; 39 for(int i=S;i!=T;i=cur[i]->y)cur[i]->w-=mi,cur[i]->re->w+=mi;flow+=mi;k=p; 40 }for(e=cur[k];e;e=e->nxt)if(e->w&&d[k]==d[e->y]+1)break; 41 if(e)cur[k]=e,k=e->y,ret[k]=e->x; 42 else{if(--gap[d[k]]==0)break;cur[k]=fch[k];int mi=n; 43 REN(k)if(e->w&&d[e->y]<mi)mi=d[e->y];d[k]=mi+1;gap[d[k]]++;if(k!=S)k=ret[k]; 44 } 45 }return flow; 46 } 47 }sol; 48 int sizn;int id1(int x,int y){return (x-1)*m+y;}int id2(int x,int y){return (x-1)*m+y+sizn;} 49 inline int read(){ 50 int x=0;bool sig=true;char ch=getchar(); 51 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=false; 52 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';return sig?x:-x; 53 } 54 inline void write(int x){ 55 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 56 int len=0;static int buf[20];while(x)buf[len++]=x%10,x/=10; 57 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 58 } 59 bool in(int x,int y){return (x-1<d)||(y-1<d)||(n-x<d)||(m-y<d);} 60 int dist(int x,int y,int x1,int y1){return (x-x1)*(x-x1)+(y-y1)*(y-y1);} 61 int S,T,cnt; 62 int main(){ 63 n=read();m=read();d=read();sizn=n*m;sol.init(sizn*2+2);S=sizn*2+1;T=sizn*2+2; 64 TIL(n){scanf("%s",s);ALL(m)map[i][j]=s[j-1]-'0';} 65 TIL(n){scanf("%s",s);ALL(m)if(s[j-1]=='L')b[i][j]=true,cnt++;} 66 TIL(n)ALL(m)if(map[i][j])sol.add(id1(i,j),id2(i,j),map[i][j]); 67 TIL(n)ALL(m)if(b[i][j])sol.add(S,id1(i,j),1); 68 TIL(n)ALL(m)if(map[i][j]&&in(i,j))sol.add(id2(i,j),T,inf); 69 TIL(n)ALL(m)if(map[i][j])for(int i2=1;i2<=n;i2++)for(int j2=1;j2<=m;j2++)if(((i^i2)||(j^j2))&&map[i2][j2]&&dist(i,j,i2,j2)<=(d*d))sol.add(id2(i,j),id1(i2,j2),inf); 70 write(cnt-sol.mxflow(S,T)); 71 return 0; 72 }
不过写起来还是很爽的。。。