[网络流24题] 深海机器人
时间限制:1 s 内存限制:128 MB
- 深海机器人问题
- «问题描述:
- 深海资源考察探险队的潜艇将到达深海的海底进行科学考察。潜艇内有多个深海机器
- 人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。深海机器人在移动中还
- 必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。每条预定
- 路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。本题限定深海机器人只
- 能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一
- 位置。
- «编程任务:
- 用一个P´Q 网格表示深海机器人的可移动位置。西南角的坐标为(0,0),东北角的坐
标为 (Q,P)。
- 给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。计算
- 深海机器人的最优移动方案,使深海机器人到达目的地后,采集到的生物标本的总价值最高。
- «数据输入:
- 由文件shinkai.in提供输入数据。文件的第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)位置坐标作为目的地。
- «结果输出:
- 程序运行结束时,将采集到的生物标本的最高总价值输出到文件shinkai.out中。
- shinkai.in
- 1 1
- 2 2
- 1 2
- 3 4
- 5 6
- 7 2
- 8 10
- 9 3
- 2 0 0
2 2 2
shinkai.out
42
1<=P,Q<=15 1<=a,b<=10
主要的难点是如何通过一个点却只计算一次价值,事实上处理方法很简单,连两次边,第一条权值为0,流量inf,第二次权值为x,流量为1。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=300; 4 const int maxm=maxn*8; 5 const int inf=0x3fffffff; 6 int a,b,p,q,num[17][17],cnt; 7 int tot=-1,fi[maxn],next[maxm],to[maxm],cost[maxm],flow[maxm]; 8 int ans,s,t,dis[maxn],que[maxn],head,tail,cur[maxn],vis[maxn]; 9 void edge_add(int x,int y,int f,int c){ 10 to[++tot]=y;next[tot]=fi[x];fi[x]=tot;cost[tot]=c;flow[tot]=f; 11 to[++tot]=x;next[tot]=fi[y];fi[y]=tot;cost[tot]=-c;flow[tot]=0; 12 } 13 bool bfs(){ 14 head=tail=1; 15 for(int i=s;i<=t;i++)cur[i]=fi[i],vis[i]=0,dis[i]=-inf; 16 que[++tail]=s;vis[s]=1;dis[s]=0; 17 while(head!=tail){ 18 head++; 19 if(head==290)head=1; 20 int u=que[head]; 21 vis[u]=0; 22 for(int i=fi[u];i+1;i=next[i]){ 23 if(flow[i]&&dis[to[i]]<dis[u]+cost[i]){ 24 dis[to[i]]=dis[u]+cost[i]; 25 if(!vis[to[i]]){ 26 vis[to[i]]=1; 27 tail++; 28 if(tail==290)tail=1; 29 que[tail]=to[i]; 30 } 31 } 32 } 33 } 34 return dis[t]!=-inf; 35 } 36 int dfs(int x,int f){ 37 vis[x]=1; 38 if(x==t)return f; 39 for(int i=cur[x];i+1;i=next[i]){ 40 cur[x]=i; 41 if(!vis[to[i]]&&flow[i]&&dis[to[i]]==dis[x]+cost[i]){ 42 int g=dfs(to[i],min(flow[i],f)); 43 if(g){ 44 ans+=cost[i]*g; 45 flow[i]-=g; 46 flow[i^1]+=g; 47 return g; 48 } 49 } 50 } 51 return 0; 52 } 53 void dinic(){ 54 while(bfs()) 55 while(dfs(s,inf)); 56 printf("%d\n",ans); 57 } 58 int main() 59 { 60 scanf("%d%d",&a,&b); 61 scanf("%d%d",&p,&q); 62 memset(fi,-1,sizeof(fi)); 63 p++;q++; 64 for(int i=1;i<=p;i++) 65 for(int j=1;j<=q;j++) 66 num[i][j]=++cnt; 67 s=0;t=cnt+1; 68 for(int i=1;i<=p;i++){ 69 for(int j=1;j<q;j++){ 70 int x; 71 scanf("%d",&x); 72 edge_add(num[i][j],num[i][j+1],inf,0); 73 edge_add(num[i][j],num[i][j+1],1,x); 74 } 75 } 76 for(int i=1;i<=q;i++){ 77 for(int j=1;j<p;j++){ 78 int x; 79 scanf("%d",&x); 80 edge_add(num[j][i],num[j+1][i],inf,0); 81 edge_add(num[j][i],num[j+1][i],1,x); 82 } 83 } 84 for(int i=1;i<=a;i++){ 85 int k,x,y; 86 scanf("%d%d%d",&k,&x,&y); 87 edge_add(s,num[x+1][y+1],k,0); 88 } 89 for(int i=1;i<=b;i++){ 90 int k,x,y; 91 scanf("%d%d%d",&k,&x,&y); 92 edge_add(num[x+1][y+1],t,k,0); 93 } 94 dinic(); 95 return 0; 96 }