• 网络流24题 20深海机器人问题


    深海机器人问题

    Time Limit 1000ms

    Memory Limit 65536K

    description

        深海资源考察探险队的潜艇将到达深海的海底进行科学考察。潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一
    位置。
        用一个P′Q 网格表示深海机器人的可移动位置。西南角的坐标为(0,0),东北角的坐标为 (Q,P)。
    
    给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。计算深海机器人的最优移动方案,使深海机器人到达目的地后,采集到的生物标本的总价值最高。

    input

    多组数据输入.
    每组输入第1 行为深海机器人的出发位置数a,和目的地数b,第2 行为P和Q 的值。接下来的P+1 行,每行有Q 个正整数,表示向东移动路径上生物标本的价值,行数据依从南到北方向排列。再接下来的Q+1 行,每行有P 个正整数,表示向北移动路径上生物标本的价值,行数据依从西到东方向排列。接下来的a行,每行有
    3 个正整数k,x,y,表示有k个深海机器人从(x,y)位置坐标出发。再接下来的b行,每行有3个正整数r,x,y,表示有r个深海机器人可选择(x,y)位置坐标作为目的地。
    
    							

    output

    每组输出采集到的生物标本的最高总价值
    
    							

    sample_input

    1 1
    2 2
    1 2
    3 4
    5 6
    7 2
    8 10
    9 3
    2 0 0
    2 2 2
    
    							

    sample_output

    42
    

    ---------------------------------------------------------------------------------------

    【问题分析】


    最大费用最大流问题。


    【建模方法】


    把网格中每个位置抽象成网络中一个节点,建立附加源S汇T。


    1、对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容量为1,费用为该边价值的有向边。
    2、对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容量为无穷大,费用为0的有向边。
    3、从S到每个出发点i连接一条容量为该点出发的机器人数量,费用为0的有向边。
    4、从每个目标点i到T连接一条容量为可以到达该点的机器人数量,费用为0的有向边。


    求最大费用最大流,最大费用流值就采集到的生物标本的最高总价值。


    【建模分析】


    这个问题可以看做是多出发点和目的地的网络运输问题。每条边的价值只能计算一次,容量限制要设为1。同时还将要连接上容量不限,费用为0的重边。由于“多个深海机器人可以在同一时间占据同一位置”,所以不需限制点的流量,直接求费用流即可。

    ---------------------------------------------------------------------------------------

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int OO=1e9;//无穷大
    const int maxm=1111111;//边的最大数量,为原图的两倍
    const int maxn=2222;//点的最大数量
    
    int node,src,dest,edge;//node节点数,src源点,dest汇点,edge边数
    int head[maxn],p[maxn],dis[maxn],q[maxn],vis[maxn];//head链表头,p记录可行流上节点对应的反向边,dis计算距离
    
    struct edgenode
    {
        int to;//边的指向
        int flow;//边的容量
        int cost;//边的费用
        int next;//链表的下一条边
    } edges[maxm];
    
    void prepare(int _node,int _src,int _dest);
    void addedge(int u,int v,int f,int c);
    bool spfa();
    
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    
    inline void prepare(int _node,int _src,int _dest)
    {
        node=_node;
        src=_src;
        dest=_dest;
        for (int i=0; i<node; i++)
        {
            head[i]=-1;
            vis[i]=false;
        }
        edge=0;
    }
    
    void addedge(int u,int v,int f,int c)
    {
        edges[edge].flow=f;
        edges[edge].cost=c;
        edges[edge].to=v;
        edges[edge].next=head[u];
        head[u]=edge++;
        edges[edge].flow=0;
        edges[edge].cost=-c;
        edges[edge].to=u;
        edges[edge].next=head[v];
        head[v]=edge++;
    }
    
    bool spfa()
    {
        int i,u,v,l,r=0,tmp;
        for (i=0; i<node; i++) dis[i]=OO;
        dis[q[r++]=src]=0;
        p[src]=p[dest]=-1;
        for (l=0; l!=r; ((++l>=maxn)?l=0:1))
        {
            for (i=head[u=q[l]],vis[u]=false; i!=-1; i=edges[i].next)
            {
                if (edges[i].flow&&dis[v=edges[i].to]>(tmp=dis[u]+edges[i].cost))
                {
                    dis[v]=tmp;
                    p[v]=i^1;
                    if (vis[v]) continue;
                    vis[q[r++]=v]=true;
                    if (r>=maxn) r=0;
                }
            }
        }
        return p[dest]>=0;
    }
    
    int spfaflow()
    {
        int i,ret=0,delta;
        while (spfa())
        {
            //按记录原路返回求流量
    
            for (i=p[dest],delta=OO; i>=0; i=p[edges[i].to])
            {
                delta=min(delta,edges[i^1].flow);
            }
            for (int i=p[dest]; i>=0; i=p[edges[i].to])
            {
                edges[i].flow+=delta;
                edges[i^1].flow-=delta;
            }
            ret+=delta*dis[dest];
        }
        return ret;
    }
    
    
    int main()
    {
        int a,b,n,m,c,u,v;
        while (~scanf("%d%d",&a,&b))
        {
            scanf("%d%d",&n,&m);
            n++;m++;
            prepare(n*m+2,0,n*m+1);
            for (int i=0;i<n;i++)
            {
                for (int j=1;j<m;j++)
                {
                    scanf("%d",&c);
                    u=i*m+j;
                    v=u+1;
                    addedge(u,v,1,-c);
                    addedge(u,v,OO,0);
                }
            }
            for (int j=1;j<=m;j++)
            {
                for (int i=0;i<n-1;i++)
                {
                    scanf("%d",&c);
                    u=i*m+j;
                    v=u+m;
                    addedge(u,v,1,-c);
                    addedge(u,v,OO,0);
                }
            }
            int i,j;
            while (a--)
            {
                scanf("%d%d%d",&c,&i,&j);
                addedge(src,i*m+j+1,c,0);
            }
            while (b--)
            {
                scanf("%d%d%d",&c,&i,&j);
                addedge(i*m+j+1,dest,c,0);
            }
            printf("%d\n",-spfaflow());
        }
        return 0;
    }
    







  • 相关阅读:
    HDU 1813 Escape from Tetris
    BZOJ 2276 Temperature
    BZOJ 4499 线性函数
    BZOJ 3131 淘金
    HDU 5738 Eureka
    POJ 2409 Let it Bead
    POJ 1286 Necklace of Beads
    POJ 1696 Space Ant
    Fox And Jumping
    Recover the String
  • 原文地址:https://www.cnblogs.com/cyendra/p/3038433.html
Copyright © 2020-2023  润新知