1. 程式人生 > >【bzoj1066】【SCOI2007】蜥蜴

【bzoj1066】【SCOI2007】蜥蜴

題目描述

在一個r行c列的網格地圖中有一些高度不同的石柱,一些石柱上站著一些蜥蜴,你的任務是讓儘量多的蜥蜴逃到邊界外。

每行每列中相鄰石柱的距離為1,蜥蜴的跳躍距離是d,即蜥蜴可以跳到平面距離不超過d的任何一個石柱上。石柱都不穩定,每次當蜥蜴跳躍時,所離開的石柱高度減1(如果仍然落在地圖內部,則到達的石柱高度不變),如果該石柱原來高度為1,則蜥蜴離開後消失。以後其他蜥蜴不能落腳。任何時刻不能有兩隻蜥蜴在同一個石柱上。


輸入

輸入第一行為三個整數r,c,d,即地圖的規模與最大跳躍距離。以下r行為石柱的初始狀態,0表示沒有石柱,1~3表示石柱的初始高度。以下r行為蜥蜴位置,“L”表示蜥蜴,“.”表示沒有蜥蜴。


輸出

輸出僅一行,包含一個整數,即無法逃離的蜥蜴總數的最小值。


樣例輸入

5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........


樣例輸出

1

 



題解

最大流。

考慮到柱子之間可以相互跳,於是要拆點。把一個點拆成入點和出點,入點出點之間連流量為柱子高度的邊。

建立超級源點,向每個蜥蜴連流量為 1 的邊。

建立超級匯點,向可以走出格子的點連流量為 inf 的邊。

可以相互到達的柱子之間連 inf 的邊。

跑最大流。

 

#include<bits/stdc++.h>
using
namespace std; #define ll long long const int maxn=20+10; const int inf=2e9; int r,c,dd,s=0,t=801,ru[1000],chu[1000],d[1000],maxflow,x,tot; int fir[1000],nex[100000],to[100000],wi[100000],ecnt; char high[maxn][maxn],Map[maxn][maxn]; bool p[800+50][800+50]; int getid(int x,int y){return (x-1)*c+y;} void add(int u,int v,int w){ nex[ecnt]
=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt++]=w; } queue<int> q; int bfs(){ memset(d,0,sizeof(d)); d[s]=1; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); for(int e=fir[u];~e;e=nex[e]){ int v=to[e]; if(wi[e]&&!d[v]){ d[v]=d[u]+1; q.push(v); } } } return d[t]; } int dfs(int u,int flow){ if(u==t) return flow; if(d[u]>=d[t]) return 0; for(int e=fir[u];~e;e=nex[e]){ int v=to[e]; if(wi[e]&&d[v]==d[u]+1&&(x=dfs(v,min(flow,wi[e])))){ wi[e]-=x; wi[e^1]+=x; return x; } } return 0; } template<typename T>inline void read(T &aa){ ll ff=1;char cc=getchar();aa=0; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar(); aa*=ff; } int main(){ read(r),read(c),read(dd); for(int i=1;i<=r;i++) cin>>high[i]+1; for(int i=1;i<=r;i++) cin>>Map[i]+1; memset(fir,-1,sizeof(fir)); for(int i=1;i<=r;i++) for(int j=1;j<=c;j++){ int id=getid(i,j); ru[id]=id;chu[id]=id+400; if(Map[i][j]=='L') add(s,ru[id],1),add(ru[id],s,0),tot++; if(i<=dd||j<=dd||(r-i+1<=dd)||(c-j+1<=dd)) add(chu[id],t,inf),add(t,chu[id],0); if(high[i][j]-48==0) continue; add(ru[id],chu[id],high[i][j]-48); add(chu[id],ru[id],0); } for(int i=1;i<=r;i++) for(int j=1;j<=c;j++){ for(int ii=1;ii<=r;ii++) for(int jj=1;jj<=c;jj++){ if(i==ii&&j==jj) continue; int id1=getid(i,j); int id2=getid(ii,jj); if(p[id1][id2]) continue; if((ii-i)*(ii-i)+(jj-j)*(jj-j)<=dd*dd){ add(chu[id1],ru[id2],inf); add(ru[id2],chu[id1],0); add(chu[id2],ru[id1],inf); add(ru[id1],chu[id2],0); } p[id1][id2]=p[id2][id1]=true; } } while(bfs()) while(dfs(s,inf)) maxflow+=x; cout<<tot-maxflow; return 0; }