zoukankan      html  css  js  c++  java
  • hdu2732 (Leapin' Lizards)

    题目链接:传送门

    题目大意:给你 n,m  n:有几行图,m是一个人最多跳m个曼哈顿距离。

         给你两张图,第一张图数字为0表示没有柱子,否则有柱子且只能跳出去 x 次(x为当前字符代表的数字)

         第二张图 '.'表示没人,'L'表示当前位置有一个人,问通过柱子之间跳跃最后最少有多少人不能逃出去。

         逃出去只能是柱子与边界的最小曼哈顿距离小于等于 m。

    题目思路:拆点网络流

         首先虚拟源汇点 S,T

         其实这道题构图建模不难想,既然某个柱子只能跳 x 次,那就把它拆为两点,连边容量为 x,这样保证合法性。

         相互之间可达的柱子连边容量 inf,因为柱子已经拆点来保证合法,所以柱子间初始化不用受限制。

         可与外界相通的柱子与 T 连边容量 inf,刚开始有人的柱子与 S 连边容量为 1。

         然后ISAP跑网络流即可。

         此题坑点:输出时注意单复数输出的不同

        久违的1A

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <cctype>
    #include <queue>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <climits>
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define fi first
    #define se second
    #define ping(x,y) ((x-y)*(x-y))
    #define mst(x,y) memset(x,y,sizeof(x))
    #define mcp(x,y) memcpy(x,y,sizeof(y))
    using namespace std;
    #define gamma 0.5772156649015328606065120
    #define MOD 1000000007
    #define inf 0x3f3f3f3f
    #define N 2000000
    #define maxn 500005
    typedef pair<int,int> PII;
    typedef long long LL;
    
    map<PII,int>M;  ///map来记录点
    int n,m,ccnt,S,T,len,peo,ans;
    int head[1000],hcnt,d[1000],pre[1000],gap[1000],cur[1000];
    char pic[50][50];
    struct Crd{int x,y,v;}co[1000];
    struct Node{int to,nxt,f;Node(){}Node(int a,int b,int c):to(a),nxt(b),f(c){}}node[N];
    bool judge(int x,int y){    ///曼哈顿距离判断
        int temp=abs(co[x].x-co[y].x);
        temp+=abs(co[x].y-co[y].y);
        return temp<=m;
    }
    inline void add(int x,int y,int f){
        node[hcnt]=Node(y,head[x],f);head[x]=hcnt++;
        node[hcnt]=Node(x,head[y],0);head[y]=hcnt++;
    }
    void ISAP(int S,int T,int n){
        ans=0;
        int aug=inf,i,flag;
        int u,e,dis;
        mst(gap,0);mst(d,0);
        for(i=0;i<=n;++i)cur[i]=head[i];
        u=pre[S]=S;
        while(d[S]<n){
            flag=0;
            for(i=cur[u];~i;i=node[i].nxt){
                e=node[i].to;
                if(node[i].f>0&&d[u]==d[e]+1){
                    flag=1;
                    break;
                }
            }
            if(flag){
                pre[e]=u;
                cur[u]=i;
                aug=min(aug,node[i].f);
                u=e;
                if(u==T){
                    while(u!=S){
                        u=pre[u];
                        node[cur[u]].f-=aug;
                        node[cur[u]^1].f+=aug;
                    }
                    u=S;
                    ans+=aug;
                    aug=inf;
                }
            }
            else{
                if(--gap[d[u]]==0)break;
                dis=n;
                cur[u]=head[u];
                for(int i=head[u];~i;i=node[i].nxt){
                    e=node[i].to;
                    if(node[i].f>0&&d[e]+1<dis){
                        dis=d[e]+1;
                        cur[u]=i;
                    }
                }
                d[u]=dis;
                ++gap[dis];
                if(u!=S)u=pre[u];
            }
        }
    }
    int main(){
        int i,j,group,Case=0;
        scanf("%d",&group);
        while(group--){
            M.clear();
            len=hcnt=0;ccnt=0;
            mst(head,-1);
            scanf("%d%d",&n,&m);
            gets(pic[1]);
            for(i=1;i<=n;++i){
                gets(pic[i]+1);
                if(!len)len=strlen(pic[i]+1);
                for(j=1;j<=len;++j){
                    if(pic[i][j]>'0'){
                        co[++ccnt].x=i;   ///ccnt是点的个数
                        co[ccnt].y=j;
                        co[ccnt].v=pic[i][j]-'0';
                        M[make_pair(i,j)]=ccnt;
                    }
                }
            }
            S=0;T=ccnt*2+1;
            for(i=1;i<=ccnt;++i){
                add(i,i+ccnt,co[i].v); ///柱子拆点连边
                if(co[i].x<=m||(n-co[i].x+1)<=m||co[i].y<=m||(len-co[i].y+1)<=m)
                    add(i+ccnt,T,inf); ///与外界相通的柱子
                for(j=1;j<i;++j){
                    if(judge(i,j)){
                        add(i+ccnt,j,inf); ///相互可达的柱子
                        add(j+ccnt,i,inf);
                    }
                }
            }
            peo=0;    ///一共多少人
            for(i=1;i<=n;++i){
                gets(pic[i]+1);
                for(j=1;j<=len;++j){
                    if(pic[i][j]=='L'){
                        ++peo;
                        int tt=M[make_pair(i,j)];
                        add(S,tt,1);
                    }
                }
            }
            ISAP(S,T,T+1);
            ans=peo-ans;  
            printf("Case #%d: ",++Case);
            if(!ans)printf("no lizard was left behind.
    ");
            else if(ans==1)printf("1 lizard was left behind.
    ");
            else printf("%d lizards were left behind.
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    判断字符中是否包含汉字
    since I lived here; since I have lived here. 的区别? 从语法上看, 为啥会有这样的区别?
    have married; have been married; 到底是结婚了没?还是已经离婚了?
    C#项目依据 x86 x64 配置不同的引用
    现在完成时可以表示过去事件对现在的影响/效果. 过去完成时也可以起相同的作用!!!!
    使用现在完成时的常见错误(转发)
    去除win10下的缺省ctrl加空格功能
    appear + 表语 与 appear to be + "表语" 的区别; get hurt与 get to be hurt的区别
    ssm搭建的一个web应用的工作流程
    return和finally究竟谁先执行,还有return是怎么返回数据的
  • 原文地址:https://www.cnblogs.com/Kurokey/p/5762416.html
Copyright © 2011-2022 走看看