bzoj1066: [SCOI2007]蜥蜴
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
题解:
把每个石柱i拆成两个点i1,i2,由i1向i2连容量为石柱高的边,如果i和j的距离不超过d,那么由i2向j1连容量为inf的边
如果能够从石柱i跳出,由i2向T连容量为inf的边
如果石柱上有蜥蜴,由S向i1连容量为1的边
然后答案为 蜥蜴数-最大流
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 850 7 #define maxm 40000 8 #define inf 1061109567 9 using namespace std; 10 char ch; 11 bool ok; 12 void read(int &x){ 13 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 14 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 15 if (ok) x=-x; 16 } 17 char h[22][22],exi[22][22]; 18 int n,m,d; 19 struct flow{ 20 int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm]; 21 int dis[maxn],head,tail,list[maxn]; 22 bool bo[maxn]; 23 void init(){s=0,t=1,tot=1,memset(now,0,sizeof(now));} 24 void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} 25 void add(int a,int b,int c){put(a,b,c),put(b,a,0);} 26 bool bfs(){ 27 memset(bo,0,sizeof(bo)); 28 head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1; 29 while (head<tail){ 30 int u=list[++head]; 31 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 32 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v; 33 } 34 return bo[t]; 35 } 36 int dfs(int u,int rest){ 37 if (u==t) return rest; 38 int ans=0; 39 for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p]) 40 if (val[p]&&dis[v]==dis[u]+1){ 41 int d=dfs(v,min(rest,val[p])); 42 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d; 43 } 44 if (!ans) dis[u]=-1; 45 return ans; 46 } 47 int dinic(){ 48 int ans=0; 49 while (bfs()) ans+=dfs(s,inf); 50 return ans; 51 } 52 }f; 53 struct Point{ 54 int x,y,dis; 55 }list[maxn]; 56 bool bo[22][22]; 57 const int dx[4]={1,0,-1,0}; 58 const int dy[4]={0,1,0,-1}; 59 int head,tail; 60 void bfs(int sx,int sy){ 61 memset(bo,0,sizeof(bo)); 62 int st=(sx-1)*m+sy; 63 bool flag=0; 64 head=0,tail=1,list[1]=(Point){sx,sy,0},bo[sx][sy]=1,f.add(st<<1,(st<<1)+1,h[sx][sy]-'0'); 65 while (head<tail){ 66 Point p=list[++head]; 67 if (p.dis==d) continue; 68 for (int i=0;i<4;i++){ 69 int x=p.x+dx[i],y=p.y+dy[i],t=(x-1)*m+y; 70 if (x<=0||x>n||y<=0||y>m){flag=1;continue;} 71 if (bo[x][y]) continue; 72 list[++tail]=(Point){x,y,p.dis+1},bo[x][y]=1; 73 if (h[x][y]!='0') f.add((st<<1)+1,t<<1,inf); 74 } 75 } 76 if (flag) f.add((st<<1)+1,f.t,inf); 77 } 78 int cnt; 79 int main(){ 80 read(n),read(m),read(d),f.init(); 81 for (int i=1;i<=n;i++) scanf("%s",h[i]+1); 82 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (h[i][j]!='0') bfs(i,j); 83 for (int i=1;i<=n;i++) scanf("%s",exi[i]+1); 84 for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (exi[i][j]=='L') f.add(f.s,((i-1)*m+j)<<1,1),cnt++; 85 printf("%d\n",cnt-f.dinic()); 86 return 0; 87 }