BZOJ1066: [SCOI2007]蜥蜴

来源:互联网 发布:欧洲网络推广代理 编辑:程序博客网 时间:2024/05/08 07:36

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

网络流
对于每根柱子 将它拆成两个点(可以理解为柱子下和柱子上) 流量为高度
这样点流量就转为了边流量
<span style="font-size:18px;">#include<bits/stdc++.h> using namespace std; const int inf=1e9+7; const int maxn=200020; int r,c,d,cnt=1,ans; char ch[21]; int mp[21][21],mark[21][21],head[802],q[802],dis[802]; struct edge{    int to,nxt,flow;}e[maxn]; inline void addedge(int x,int y,int fl){    e[++cnt].to=y;    e[cnt].nxt=head[x];    head[x]=cnt;    e[cnt].flow=fl;    e[++cnt].to=x;    e[cnt].nxt=head[y];    head[y]=cnt;    e[cnt].flow=0;} bool judge(int x1,int y1,int x2,int y2){    if(mp[x1][y1]&&mp[x2][y2]&&(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=d*d)        return true;    return false;} inline bool bfs(){    int ql=0,qr=1;    q[1]=0;    memset(dis,0,sizeof(dis));    dis[0]=1;    while(ql<qr)    {        int x=q[++ql];        for(int i=head[x];i;i=e[i].nxt)        {            int y=e[i].to;            if(e[i].flow&&!dis[y])            {                dis[y]=dis[x]+1;                q[++qr]=y;            }        }    }    if(dis[801]) return true;    return false;} inline int dfs(int x,int flow){    if(x==801) return flow;    int d,used=0;    for(int i=head[x];i;i=e[i].nxt)    {        int y=e[i].to;        if(e[i].flow&&dis[y]==dis[x]+1)        {            d=dfs(y,min(flow,e[i].flow));            e[i].flow-=d;            e[i^1].flow+=d;            used+=d;            if(used==flow)                return flow;        }    }    if(!used)        dis[x]=-1;    return used;} inline void dinic(){    while(bfs())        ans-=dfs(0,inf);} int main(){    scanf("%d%d%d",&r,&c,&d);    for(int i=1;i<=r;i++)    {        scanf("%s",ch);        for(int j=0;j<c;j++)            mp[i][j+1]=ch[j]-'0';    }    int tot=0;    for(int i=1;i<=r;i++)            for(int j=1;j<=c;j++)            mark[i][j]=++tot;    for(int i=1;i<=r;i++)    {        scanf("%s",ch);        for(int j=0;j<c;j++)            if(ch[j]=='L')                ans++,addedge(0,mark[i][j+1],1);    }    for(int i=1;i<=d;i++)        for(int j=d+1;j<=r-d;j++)        {            addedge(mark[j][i]+400,801,inf);            addedge(mark[j][c-i+1]+400,801,inf);        }    for(int i=1;i<=d;i++)        for(int j=1;j<=c;j++)        {            addedge(mark[i][j]+400,801,inf);            addedge(mark[r-i+1][j]+400,801,inf);        }    for(int x1=1;x1<=r;x1++)    {        for(int y1=1;y1<=c;y1++)        {            for(int x2=x1-d;x2<=x1+d;x2++)            {                for(int y2=y1-d;y2<=y1+d;y2++)                {                    if(judge(x1,y1,x2,y2)&&(x1!=x2||y1!=y2))                    {                        addedge(mark[x1][y1]+400,mark[x2][y2],inf);                    }                }            }        }    }    for(int i=1;i<=r;i++)            for(int j=1;j<=c;j++)            if(mp[i][j])                addedge(mark[i][j],mark[i][j]+400,mp[i][j]);    dinic();    cout<<ans;}</span>

0 0