zoukankan      html  css  js  c++  java
  • 网络流建模关键1:有点的流量限。

     [SCOI2007]蜥蜴

    在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。
    每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

    【输入】
    输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

    【输出】
    输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

    【样例输入】
    5 8 2
    00000000
    02000000
    00321100
    02000000
    00000000
    ........
    ........
    ..LLLL..
    ........
    ........

    【样例输出】
    1

    【限制】
    100%的数据满足:1<=r, c<=20, 1<=d<=3

    这道题关键在于每个点有点的流量,遇到这种情况通常将一个拆成两个点,一条弧。

    并且这种建模还有两个关键,就是自设源点和汇点。

    代码如下用的直接定义法EK

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define RC 20+2
    #define inf 1e9
    #define E 50000
    #define N 4000+1 
    using namespace std;
    char g1[RC][RC],g2[RC][RC];
    int map[RC][RC];
    int used[E],way[E];
    int head[N],arnum=1;
    struct arc{
        int next,to,cap;
    }ar[E];
    void add(int from,int to,int cap)
    {
        ar[++arnum].next=head[from];
        ar[arnum].to=to;
        ar[arnum].cap=cap;
        head[from]=arnum;
    }
    void insert(int from,int to,int cap){add(from,to,cap);add(to,from,0);}
    int ans;
    void work(int step)
    {
        ans+=1;
        for(int i=1;i<=step;i++)ar[way[i]].cap--,ar[way[i]^1].cap++;
    }
    int dfs(int u,int en,int step)
    {
        used[u]=1;
        for(int i=head[u];i;i=ar[i].next)
        {
            int v=ar[i].to;
            int cap=ar[i].cap;
            if(!used[v]&&cap>0)
            {
                way[step]=i;
                if(v==en){work(step);return 1;}
                else if(dfs(v,en,step+1))return 1;
            }
        }
        return 0;
    }
    int main()
    {
        int r,c,d;scanf("%d%d%d",&r,&c,&d);
        int rank=0;
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
            {    
                cin>>g1[i][j];
                if(g1[i][j]!='0')
                {
                    rank++;
                    map[i][j]=rank;
                    insert(rank,rank+450,g1[i][j]-48);
                }
            }        
        int st=0;
        int cnt=0;
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
            {
                cin>>g2[i][j];
                if(g2[i][j]=='L')
                    insert(st,map[i][j],1),cnt++;
            }    
        int en=N-1;
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
            {
                if(g1[i][j]!='0')
                {
                    for(int k=1;k<=r;k++)
                        for(int h=1;h<=c;h++)
                        {
                            double dx=abs(k-i);
                            double dy=abs(h-j);
                            if(hypot(dx,dy)&&sqrt(d*d)>=hypot(dx,dy)&&g1[k][h]!='0')
                                insert(map[i][j]+450,map[k][h],inf);
                        }
                    if(r-i<d||i-1<d||c-j<d||j-1<d)
                        insert(map[i][j]+450,en,inf);            
                }
            }
        for(;;)
        {
            memset(used,0,sizeof(used));
            if(!dfs(st,en,1))break;
        }
        printf("%d",(cnt-ans)?(cnt-ans):0);
        return 0;
    }
  • 相关阅读:
    [GoogleAppEngine]编译问题-locale zh_CN
    [Android]Webview中JS接口调用Java-版本问题
    [HTTP基础]3. HTTP链接
    [WebView]简单总结
    [HTTP基础]1.网络开发必备的HTTP协议知识
    [HTTP基础]2.Http和Socket区别
    [HTTP]Android抓包方法(Wireshark)
    [Android]Process&Thread-基本原理
    [Android]Thread两种实现方法
    [Android]消息队列模型——Thread,Handler,Looper,Massage Queue
  • 原文地址:https://www.cnblogs.com/star-eternal/p/7631199.html
Copyright © 2011-2022 走看看