[網絡流24題] 深海機器人
阿新 • • 發佈:2018-01-02
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題] 深海機器人