深海机器人问题

题目背景

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

题目描述

用一个 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 }

 

posted @ 2017-10-30 19:44  Z-Y-Y-S  阅读(310)  评论(0编辑  收藏  举报