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;
}

 

posted @ 2019-09-21 19:53  wangyiding  阅读(181)  评论(0编辑  收藏  举报