BZOJ 1066 [SCOI2007]蜥蜴

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 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..
........
........

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 }

不过写起来还是很爽的。。。

你可能感兴趣的:(BZOJ 1066 [SCOI2007]蜥蜴)