1. 程式人生 > >[網絡流24題] 深海機器人

[網絡流24題] 深海機器人

display body 移動 include ble urn 東北 進行 整數

[網絡流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 }
View Code

[網絡流24題] 深海機器人