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