【HDU】 2732 Leapin' Lizards

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;
}

你可能感兴趣的:(【HDU】 2732 Leapin' Lizards)