原题地址
题目描述
深海资源考察探险队的潜艇将到达深海的海底进行科学考察。
潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。
深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。
每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。
本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。
用一个 $ ext{P} imes ext{Q}$网格表示深海机器人的可移动位置。西南角的坐标为 $(0,0)$ ,东北角的坐标为 $(Q,P)$ 。
给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。
计算深海机器人的最优移动方案, 使深海机器人到达目的地后,采集到的生物标本的总价值最高。
输入和输出
输入
文件的第 1 行为深海机器人的出发位置数 $ ext a$,和目的地数 $ ext{b}$ 。
第 2 行为 $ ext{P}$ 和 $ ext{Q}$ 的值。
接下来的 $ ext{P} +1$ 行,每行有 $ ext{Q}$ 个正整数,表示向东移动路径上生物标本的价值,行数据依从南到北方向排列。
再接下来的 $ ext{Q} +1 $ 行,每行有 $ ext{P}$ 个正整数,表示向北移动路径上生物标本的价值,行数据依从西到东方向排列。
接下来的 $ ext{a}$ 行,每行有 3 个正整数 $ ext{k,x,y}$ ,表示有 $ ext{k}$ 个深海机器人从 $( ext{x,y})$ 位置坐标出发。
再接下来的 $ ext{b}$ 行,每行有 3 个正整数 $ ext{r,x,y}$ ,表示有 $ ext{r}$ 个深海机器人可选择 $( ext{x,y})$ 位置坐标作为目的地。
输出
输出采集到的生物标本的最高总价值。
样例
输入
1 1
2 2
1 2
3 4
5 6
7 2
8 10
9 3
2 0 0
2 2 2
输出
42
数据范围和提示
$1≤P,Q≤15$
$1leq aleq 4$
$1leq bleq 6$
思路
由标题可知,依然是网络流。
相邻的点要连两条边,一条流量为 1 费用为标本价值,另一条流量为无限,费用为 0 。解释:两种情况:第一个机器人拿到了标本;之后的机器人单纯地经过这个点。
建图的时候费用取相反数,然后跑最小费用最大流就可以求出最大价值了。
代码
#include
#define maxn 8000
#define pu(i,j) ((i-1)*Q+j)
using namespace std;
struct Edge{
int to,next,flow,cost;
Edge(int a=0,int b=0,int c=0,int d=0){
to=a,next=b,flow=c,cost=d;
}
}l[maxn<<5];
struct Node{
int pre,id;
Node(int a=0,int b=0){
pre=a,id=b;
}
}cha[maxn];
int head[maxn],cnt=1,dis[maxn],vis[maxn],s,t;
int neflow[maxn],maxflow,mincost;
inline void Add(int a,int b,int c,int d){
l[++cnt]=Edge(b,head[a],c,d);head[a]=cnt;
l[++cnt]=Edge(a,head[b],0,-d);head[b]=cnt;
}
inline bool spfa(){
queueq;
fill(dis+1,dis+t+1,INT_MAX);
q.push(s);dis[s]=0;
neflow[s]=INT_MAX;
while(!q.empty()){
int hq=q.front();q.pop();vis[hq]=0;
for (int i=head[hq];i;i=l[i].next){
int v=l[i].to;
if (dis[v]>dis[hq]+l[i].cost&&l[i].flow){
dis[v]=dis[hq]+l[i].cost;
neflow[v]=min(neflow[hq],l[i].flow);
cha[v]=Node(hq,i);
if (!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
return dis[t]