(http://www.elijahqi.win/2017/12/18/loj6224%E3%80%8C%E7%BD%91%E7%BB%9C%E6%B5%81-24-%E9%A2%98%E3%80%8D%E6%B7%B1%E6%B5%B7%E6%9C%BA%E5%99%A8%E4%BA%BA%E9%97%AE%E9%A2%98/%20%E2%80%8E)
题目描述
深海资源考察探险队的潜艇将到达深海的海底进行科学考察。
潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。
深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。
每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。
本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。
用一个 P×Q\text{P} \times \text{Q}P×Q 网格表示深海机器人的可移动位置。西南角的坐标为 (0,0)(0,0)(0,0) ,东北角的坐标为 (Q,P)(Q,P)(Q,P) 。
给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。
计算深海机器人的最优移动方案, 使深海机器人到达目的地后,采集到的生物标本的总价值最高。
233
输入格式
文件的第 1 行为深海机器人的出发位置数 a,和目的地数 b\text{b}b 。
第 2 行为 P\text{P}P 和 Q\text{Q}Q 的值。
接下来的 P+1\text{P} +1P+1 行,每行有 Q\text{Q}Q 个正整数,表示向东移动路径上生物标本的价值,行数据依从南到北方向排列。
再接下来的 Q+1\text{Q} +1 Q+1 行,每行有 P\text{P}P 个正整数,表示向北移动路径上生物标本的价值,行数据依从西到东方向排列。
接下来的 a\text{a}a 行,每行有3 个正整数 k,x,y\text{k,x,y}k,x,y,表示有 k\text{k}k 个深海机器人从 (x,y)(\text{x,y})(x,y)位置坐标出发。
再接下来的 b\text{b}b 行,每行有 3 个正整数 r,x,y\text{r,x,y}r,x,y ,表示有 r\text{r}r 个深海机器人可选择 (x,y)(\text{x,y})(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≤151\leq P,Q\leq151≤P,Q≤15
1≤a≤41≤a≤41≤a≤4 1\leq a\leq 41 \leq a \leq 4 1\leq a\leq 41≤a≤41≤a≤41≤a≤4
1≤b≤61\leq b\leq 61≤b≤6
直接按照题意建边 然后每个边都增设一个权值为inf费用为0的边 表示可以经过 然后最大费用流即可
#include<queue>#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 400
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}
return x;
}
struct node{
int x,y,z,next,c;
}data[N*N];
int num=1,h[N],f[N],pre[N],path[N],id[20][20],a,b,p,q,T;bool flag[N];
inline void insert1(int x,int y,int z,int c){
data[++num].y=y;data[num].next=h[x];data[num].z=z;data[num].c=c;data[num].x=x;h[x]=num;
data[++num].y=x;data[num].next=h[y];data[num].z=0;data[num].c=-c;data[num].x=y;h[y]=num;
}
inline bool spfa(){
queue<int>q;memset(flag,0,sizeof(flag));memset(f,128,sizeof(f));f[0]=0;flag[0]=1;memset(pre,-1,sizeof(pre));q.push(0);
while(!q.empty()){
int x=q.front();q.pop();flag[x]=0;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y,z=data[i].z,c=data[i].c;
if (f[x]+c>f[y]&&z){
f[y]=f[x]+c;pre[y]=x;path[y]=i;
if (!flag[y]) q.push(y),flag[y]=1;
}
}
}
if (pre[T]==-1) return 0;else return 1;
}
int main(){
freopen("loj.in","r",stdin);
a=read();b=read();p=read();q=read();T=(p+1)*(q+1)+1;int tot=0;
for (int i=1;i<=p+1;++i)
for (int j=1;j<=q+1;++j) id[i][j]=++tot;
for (int i=1;i<=p+1;++i)
for (int j=1;j<=q;++j) insert1(id[i][j],id[i][j+1],1,read()),insert1(id[i][j],id[i][j+1],inf,0);
for (int i=1;i<=q+1;++i)
for (int j=1;j<=p;++j) insert1(id[j][i],id[j+1][i],1,read()),insert1(id[j][i],id[j+1][i],inf,0);
for (int i=1;i<=a;++i){
int k=read(),x=read()+1,y=read()+1;insert1(0,id[x][y],k,0);
}
for (int i=1;i<=b;++i){
int k=read(),x=read()+1,y=read()+1;insert1(id[x][y],T,k,0);
}int ans=0;
// for (int i=2;i<=num;++i) printf("%d %d %d %d\n",data[i].x,data[i].y,data[i].z,data[i].c);
while(spfa()){
int minn=inf,now=T;
while(now) minn=min(minn,data[path[now]].z),now=pre[now];now=T;
while(now) {ans+=data[path[now]].c*minn;data[path[now]].z-=minn;data[path[now]^1].z+=minn;now=pre[now];}
}printf("%d",ans);
return 0;
}