HDU 2732 Leapin' Lizards (最大流)

来源:互联网 发布:flash for mac 破解版 编辑:程序博客网 时间:2024/06/10 01:01

题目链接
题目大意:有一些蜥蜴在一些迷宫里,迷宫的行数为n列数没给,每个蜥蜴每次可以跳跃的最大距离为d,现在给出两个矩阵,第一个描述的是每个位置最多可以被走几次,第二个描述的是哪里有蜥蜴,问最少有几只蜥蜴无法走出迷宫。
分析建图:
这也是一个最大流问题,通过贪心的思想可以知道:
如果一个位置能够直接跳出迷宫,那么最优方案肯定是直接跳出,于是可以将这些点直接与汇点相连。
因为每一个点有被使用的次数,所以可以拆点,点l和点r的流量为他可以使用的次数。
然后剩下的点与能都到达它的点相连接,边权为inf。
蜥蜴和源点相连边权为1 因为每个点最多只有一个蜥蜴。
然后跑一遍最大流得出蜥蜴总数减去最大流就是答案啦。要注意输出有分单复数形式~~~这里wa了一发。

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<math.h>#include<vector>using namespace std;#define inf 2000000000#define MAXN 4555char mapa[50][50];char mapb[50][50];int vis[50][50];struct tree{    int from,to,cap,flow;    tree(){}    tree(int ff,int tt,int cc,int ww)    {        from=ff;to=tt;cap=cc;flow=ww;    }};vector<tree>G;vector<int>v[MAXN];int cur[MAXN];int d[MAXN];int source,sink;int q[200010];void addtree(int from,int to,int cap){    G.push_back(tree(from,to,cap,0));    G.push_back(tree(to,from,0,0));    int m=G.size();    v[from].push_back(m-2);    v[to].push_back(m-1);}bool bfs()    {        memset(d,-1,sizeof(d));        int front=0;int back=0;        q[back++]=source;        d[source]=0;        while(front<back)        {            int u=q[front++];            if(u==sink) return true;  //只有d[x]+1=d[e.to]才能继续遍历             for(int i=0;i<v[u].size();i++)            {                tree &e=G[v[u][i]];                if(d[e.to]==-1&&e.flow<e.cap)                {                    d[e.to]=d[u]+1;                    q[back++]=e.to;                }            }        }        return false;    }int dfs(int x,int a){    if(x==sink||a==0)    return a;    int flow=0,f;    for(int &i=cur[x];i<v[x].size();i++)    {        tree &e=G[v[x][i]];        if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)        {            e.flow+=f;            G[v[x][i]^1].flow-=f;            flow+=f;            a-=f;            if(a==0)            break;        }    }    if (!flow) d[x] = -2; //当边为0时,应从残量网络中删去,防止重新搜索     return flow;}int maxflow(){    int flow=0;    while(bfs())    {        memset(cur,0,sizeof(cur));        flow+=dfs(source,inf);    }    return flow;}int main(){    int T;    scanf("%d",&T);    int cas=0;    while(T--)    {        memset(vis,0,sizeof(vis));        for(int i=0;i<MAXN;i++)        v[i].clear();        G.clear();        int n,m,d;        scanf("%d%d",&n,&d);        source=1,sink=2000;        for(int i=0;i<n;i++)        scanf("%s",mapa[i]);        for(int i=0;i<n;i++)        scanf("%s",mapb[i]);        m=strlen(mapa[0]);        int lizard=0;        for(int i=0;i<n;i++)        {            for(int j=0;j<m;j++)            {                //if(mapa[i][j]-'0')                addtree(i*m+j+2,i*m+j+1002,mapa[i][j]-'0');                if(mapb[i][j]=='L')                {                    lizard++;                    addtree(source,i*m+j+2,1);                }                for(int k=-d;k<=d;k++)                {                    for(int l=-d;l<=d;l++)                    {                        if(abs(k)+abs(l)>d) continue;                        if(i+k<0||i+k>=n||j+l<0||j+l>=m)                        {                            if(vis[i][j]) continue;                            vis[i][j]=1;                            addtree(i*m+j+1002,sink,inf);                            continue;                        }                        if(mapa[i][j]-'0'!=0)                        addtree(i*m+j+1002,(i+k)*m+j+l+2,inf);                    }                }            }        }        printf("Case #%d: ",++cas);        int ans=lizard-maxflow();        if(ans==0)printf("no lizard was left behind.\n");        else if(ans==1)printf("1 lizard was left behind.\n");        else printf("%d lizards were left behind.\n",ans);    }}
0 0