• P4012 深海机器人问题


    题目描述

    深海资源考察探险队的潜艇将到达深海的海底进行科学考察。

    潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。

    深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。

    每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。

    本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。

    用一个 P×Q 网格表示深海机器人的可移动位置。西南角的坐标为 (0,0),东北角的坐标为 (Q,P) 。

    给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。

    计算深海机器人的最优移动方案, 使深海机器人到达目的地后,采集到的生物标本的总价值最高。

    输入格式

    文件的第 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)位置坐标作为目的地。

    a行和b行输入时横纵坐标要反过来

    输出格式

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

    输入输出样例

    输入 #1
    1 1
    2 2
    1 2
    3 4
    5 6
    7 2
    8 10
    9 3
    2 0 0
    2 2 2
    输出 #1
    42

    说明/提示

    1≤P,Q≤15

    1≤a≤41

    1≤b≤61

    思路

    首先这是一道求路线的费用最大问题,对于每一个起点和终点都是可以看做一类,因此对于每一类我们可以考虑如何转移。首先源点连所有的起点,汇点连所有的终点,之后考虑起点到终点的移动。对于网格,只能向上和向右移动,因此我们对每个点可以拆点建边。先连一个容量为1,费用为cij的边,再连一个容量为inf,费用为0的边。我们再跑一遍最大费用最大流即可得到答案。

    代码

    #include<bits/stdc++.h>
    #define N 10700
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int y,z,p,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0,ans=0;
    int n,m,s,t;
    void add(int x,int y,int z,int p){
        e[++tot].y=y;e[tot].z=z;e[tot].p=p;e[tot].next=head[x];head[x]=tot;
        e[++tot].y=x;e[tot].z=0;e[tot].p=-p;e[tot].next=head[y];head[y]=tot;
    }
    int incf[N],v[N],pre[N],d[N];
    bool spfa(){
        queue<int> q;
        memset(d,0x3f,sizeof(d));// 0xcf
        memset(v,0,sizeof(v));
        q.push(s);d[s]=0;v[s]=1;
        incf[s]=inf;
        while(q.size()){
            int x=q.front();v[x]=0;q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(!z) continue;
                if(d[y]>d[x]+e[i].p){//d[y]<d[x]+e[i].p
                    d[y]=d[x]+e[i].p;
                    incf[y]=min(incf[x],z);
                    pre[y]=i;
                    if(!v[y]) v[y]=1,q.push(y);
                }
            }
        }
        if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf
        return true;
    }
    void update(){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].z-=incf[t];
            e[i^1].z+=incf[t];
            x=e[i^1].y; 
        }
        maxflow+=incf[t];
        ans+=d[t]*incf[t];
    }
    # define pu(x,y) (x-1)*Q+y
    int main()
    {
        int a,b,P,Q;
        scanf("%d%d%d%d",&a,&b,&P,&Q);
        P++,Q++;s=0;t=1000;
        for(int i=1;i<=P;i++)
          for(int j=1;j<Q;j++)
            {
                int x,hh=pu(i,j),tt=hh+1;
                scanf("%d",&x);
                add(hh,tt,1,-x);
                add(hh,tt,inf,0);
            }
        for(int j=1;j<=Q;j++)
          for(int i=1;i<P;i++)
            {
                int x,hh=pu(i,j),tt=hh+Q;
                scanf("%d",&x);
                add(hh,tt,1,-x);
                add(hh,tt,inf,0);
            }
        for(int i=1;i<=a;i++)
          {
              int k,x,y;
              scanf("%d%d%d",&k,&x,&y);
              x++,y++;
              add(s,pu(x,y),k,0);
          }
        for(int i=1;i<=b;i++)
          {
              int k,x,y;
              scanf("%d%d%d",&k,&x,&y);
              x++,y++;
              add(pu(x,y),t,k,0);
          }
        while(spfa()) update();
        cout<<-ans<<endl;
        return 0;
    }
  • 相关阅读:
    整理了一份FAQ,新手看一下
    分享:pythonbitstring 3.1.2 发布
    分享:TokuDB v7 发布,并宣布全面开源
    在美国学CS能挣多少钱?美国IT公司标准 offer package详细数字及绿卡政策 | 美国留学申请与就业找工作咨询博客|Warald|一亩三分地论坛
    写的split带改进
    分享:一个多进程并发执行程序ps命令 ls命令
    分享:vi/vim使用进阶: 指随意动,移动如飞 (一)
    waning rm i rm rvfi
    分享:C++中头文件、源文件之间的区别与联系
    分享:神奇的动归状态转移方程——最优子序列
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11564371.html
Copyright © 2020-2023  润新知