【HDU】 2732 Leapin' Lizards

来源:互联网 发布:围棋记谱软件安卓版 编辑:程序博客网 时间:2024/06/08 20:09

Leapin’ Lizards


题目链接

  • Leapin’Lizards

题目大意

给你两个图,一个用0,1,2,3表示,一个用 L 或 . 表示。其中用L表示的图中,有L的位置表示有蜥蜴,没有L的位置表示没有蜥蜴。用数字表示的图中,数字表示当前位置柱子的高度,每次一个蜥蜴可以从一个柱子跳到距离d以内的另外一个柱子,每跳跃一次,当前柱子的高度就减一,问最后会有多少只蜥蜴被困在里面。


题解

首先,可以明显的看到,一个柱子是有固定的通过次数的,这一点跟网络流中边的属性很像,但是这里的柱子是点,并不是边,对于这样的情况,在这里我们采用拆点的方法
把一根柱子拆成两个点,一条边,从第一个点向第二个点连一条有向边,权为这个柱子的高度,在从第二个点向所有能到达的其他柱子构造一条边,权可以设为无穷(一定可通过)。最后,能跳出的点连向汇点,构造源点向所有有蜥蜴的点连一条权为1的边。至此,构图完毕。
解法即是在以上图上做一遍最大流,即可得到解。


代码

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#define INF 0x7fffffff;using namespace std;int T,n,d,a[1005][1005],flow[1005],pre[1005],q[1005],node[25][25];char s[25][25];int bfs(int s,int des,int k){    int h=0,t=0;    memset(q,0,sizeof(q));    memset(pre,0,sizeof(pre));    q[h++]=s; pre[s]=s; flow[s]=INF; flow[des]=0;    while (h!=t)    {        int u=q[t];        if (u==des) break;        for (int v=1;v<=k;v++) if (a[u][v]>0 && !pre[v])        {            pre[v]=u; q[h++]=v;            flow[v]=min(flow[u],a[u][v]);        }        t++;    }    if (pre[des]==0) return 0;    else return flow[des];}int maxflow(int s,int des,int k){    int t,ans=0;    while (t=bfs(s,des,k),t!=0)    {        for (int i=des;i!=s;i=pre[i])        {            a[pre[i]][i]-=t;            a[i][pre[i]]+=t;        }        ans+=t;    }    return ans;}int main(){    int Case=1;    scanf("%d",&T);    while (T--)    {        memset(flow,0,sizeof(flow));        memset(a,0,sizeof(a));        memset(node,0,sizeof(node));        memset(s,0,sizeof(s));        scanf("%d%d",&n,&d);        for (int i=0;i<n;i++) scanf("%s",&s[i]);        int m=strlen(s[0]),t=2;        for (int i=0;i<n;i++)            for (int j=0;j<m;j++) if (s[i][j]!='0')        {            node[i][j]=t;            a[t][t+1]=s[i][j]-'0';            t+=2;        }        for (int i=0;i<n;i++)            for (int j=0;j<m;j++) if (s[i][j]!='0' && (i+1<=d || j+1<=d || n-i<=d || m-j<=d)) a[node[i][j]+1][t]=INF;        for (int i1=0;i1<n;i1++)            for (int j1=0;j1<m;j1++)            for (int i2=0;i2<n;i2++)            for (int j2=0;j2<m;j2++)            if (s[i1][j1]!='0' && s[i2][j2]!=0 && abs(i1-i2)+abs(j1-j2)<=d)        {            //node[i1][j1]+1->node[i2][j2]            a[node[i1][j1]+1][node[i2][j2]]=INF;        }        for (int i=0;i<n;i++) scanf("%s",&s[i]);        int l=0;        for (int i=0;i<n;i++)            for (int j=0;j<m;j++) if (s[i][j]=='L')            {                if (node[i][j]) a[1][node[i][j]]=1;                l++;            }        int ans=l-maxflow(1,t,t);        printf("Case #%d: ",Case++);        if (ans==0) printf("no lizard was left behind.\n");        else if (ans==1) printf("1 lizard was left behind.\n");        else if (ans>=2) printf("%d lizards were left behind.\n",ans);    }    return 0;}
0 0
原创粉丝点击