题目背景

深海资源考察探险队的潜艇将到达深海的海底进行科学考察。潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。深海 机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。每条预定路径上的生物标本的价值是已知的,而且生物标本只能 被采集一次。本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。

题目描述

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

给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。计算深海机器人的最优移动方案,使深海机器人到达目的地后,采集到的生物标本的总价值最高。

输入输出格式

输入格式:

由文件 input.txt 提供输入数据。文件的第 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.txt 中。

输入输出样例

输入样例#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
最小费用流
每一个起点和源点连一条流量为机器数量权为0的边,写为<c,0>
每一个终点和源点连一条<c,0>的边
由于每一个边可以无限经过,又只有一个可以得到价值
所以对于每一个边建一条<1,-val>和一条<inf,0>
然后做最小费用流,因为求最大值,所以边权取负,输出×(-1)
因为可以多次经过,所以不需要拆点,只要给带权值的边限流


1 #include<iostream>   2 #include<cstdio>   3 #include<cstring>   4 #include<algorithm>   5 #include<queue>   6 using namespace std;   7 struct Node   8 {   9   int next,to,c,dis,u;  10 }edge[20001];  11 int head[1001],num=1,inf;  12 int A,B,n,m,path[2001],dist[2001],ans,flow,map[1001][1001];  13 bool vis[1001];  14 void add(int u,int v,int c,int dis)  15 {  16   num++;  17   edge[num].next=head[u];  18   head[u]=num;  19   edge[num].to=v;  20   edge[num].c=c;  21   edge[num].dis=dis;  22   edge[num].u=u;  23   num++;  24   edge[num].next=head[v];  25   head[v]=num;  26   edge[num].to=u;  27   edge[num].c=0;  28   edge[num].dis=-dis;  29   edge[num].u=v;  30 }  31 bool SPFA(int S,int T)  32 {  33     int i;  34     queue<int>Q;  35     memset(path,-1,sizeof(path));  36     memset(dist,127/2,sizeof(dist));  37     Q.push(S);  38     inf=dist[0];  39     dist[S]=0;  40     memset(vis,0,sizeof(vis));  41     while (Q.empty()==0)  42     {  43         int u=Q.front();  44         Q.pop();  45         vis[u]=0;  46         for (i=head[u]; i!=-1; i=edge[i].next)  47             if(edge[i].c>0)  48             {  49                 int v=edge[i].to;  50                 if (dist[v]>dist[u]+edge[i].dis)  51                 {  52                     dist[v]=dist[u]+edge[i].dis;  53                     path[v]=i;  54                     if (vis[v]==0)  55                     {  56                         vis[v]=1;  57                         Q.push(v);  58                     }  59                 }  60             }  61     }  62     if (dist[T]==inf) return 0;  63     return 1;  64 }  65 int mincost(int S,int T)  66 {int i;  67   while (SPFA(S,T))  68     {  69       int minf=inf;  70       for (i=path[T];i!=-1;i=path[edge[i].u])  71     minf=min(minf,edge[i].c);  72       for (i=path[T];i!=-1;i=path[edge[i].u])  73     {  74       edge[i].c-=minf;  75       edge[i^1].c+=minf;  76       ans+=edge[i].dis*minf;  77     }  78       flow+=minf;  79     }   80   return ans;  81 }  82 int main()  83 {int x,i,j,k,y;  84   cin>>A>>B;  85   cin>>n>>m;  86   x=0;  87   memset(head,-1,sizeof(head));  88   memset(map,127/2,sizeof(map));  89   inf=map[0][0];  90   for (i=0;i<=n;i++)  91     for (j=0;j<=m;j++)  92       map[i][j]=++x;  93   for (i=0;i<=n;i++)  94     {  95       for (j=0;j<m;j++)  96     {  97       scanf("%d",&x);  98       add(map[i][j],map[i][j+1],1,-x);  99       add(map[i][j],map[i][j+1],inf,0); 100     } 101     } 102   for (j=0;j<=m;j++) 103     { 104       for (i=0;i<n;i++) 105     { 106       scanf("%d",&x); 107       add(map[i][j],map[i+1][j],1,-x); 108       add(map[i][j],map[i+1][j],inf,0); 109     } 110     } 111   for (i=1;i<=A;i++) 112     { 113       scanf("%d%d%d",&k,&x,&y); 114       add(0,map[x][y],k,0); 115     } 116   for (i=1;i<=B;i++) 117     { 118       scanf("%d%d%d",&k,&x,&y); 119       add(map[x][y],(n+1)*(m+1)+1,k,0); 120     } 121   cout<<-mincost(0,(n+1)*(m+1)+1); 122 }