洛谷P4012 深海機器人問題(費用流)
題目描述
深海資源考察探險隊的潛艇將到達深海的海底進行科學考察。
潛艇內有多個深海機器人。潛艇到達深海海底後,深海機器人將離開潛艇向預定目標移動。
深海機器人在移動中還必須沿途采集海底生物標本。沿途生物標本由最先遇到它的深海機器人完成采集。
每條預定路徑上的生物標本的價值是已知的,而且生物標本只能被采集一次。
本題限定深海機器人只能從其出發位置沿著向北或向東的方向移動,而且多個深海機器人可以在同一時間占據同一位置。
用一個 P\times QP×Q 網格表示深海機器人的可移動位置。西南角的坐標為 (0,0)(0,0) ,東北角的坐標為 (Q,P)(Q,P) 。
給定每個深海機器人的出發位置和目標位置,以及每條網格邊上生物標本的價值。
計算深海機器人的最優移動方案, 使深海機器人到達目的地後,采集到的生物標本的總價值最高。
輸入輸出格式
輸入格式:
文件的第 11 行為深海機器人的出發位置數 aa ,和目的地數 bb 。
第 22 行為 PP 和 QQ 的值。
接下來的 P+1P+1 行,每行有 QQ 個正整數,表示向東移動路徑上生物標本的價值,行數據依從南到北方向排列。
再接下來的 Q+1Q+1 行,每行有 PP 個正整數,表示向北移動路徑上生物標本的價值,行數據依從西到東方向排列。
接下來的 aa 行,每行有 33 個正整數 k,x,yk,x,y ,表示有 kk 個深海機器人從 (x,y)(x,y) 位置坐標出發。
再接下來的 bb 行,每行有 33 個正整數 r,x,yr,x,y ,表示有 rr 個深海機器人可選擇 (x,y)(x,y) 位置坐標作為目的地。
a行和b行輸入時橫縱坐標要反過來
輸出格式:
輸出采集到的生物標本的最高總價值.
輸入輸出樣例
輸入樣例#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
說明
1\leq P,Q\leq151≤P,Q≤15
1\leq a\leq 41≤a≤4
1\leq b\leq 61≤b≤6
費用流應該比較顯然
就是讀入比較坑爹
需要把整張圖反過來
從S向每個機器人開始的地方連容量為機器人數量,費用為0的邊
從每個機器人向T連容量為數量,費用為0的邊
相鄰格子之間連一條容量為INF,費用為0的邊,再連一條容量為1,費用為讀入的邊
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0) using namespace std; const int INF=1e8+10; const int MAXN=1001+10; int N,M,S,T; int C[MAXN][MAXN]; struct node { int u,v,w,f,nxt; }edge[MAXN]; int head[MAXN],num=2; inline void add_edge(int x,int y,int z,int f) { edge[num].u=x; edge[num].v=y; edge[num].w=z; edge[num].f=f; edge[num].nxt=head[x]; head[x]=num++; } int dis[MAXN],vis[MAXN],Pre[MAXN]; bool SPFA() { memset(dis,0xf,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int>q; q.push(S); dis[S]=0; while(q.size()!=0) { int p=q.front();q.pop(); vis[p]=0; for(int i=head[p];i!=-1;i=edge[i].nxt) { if(edge[i].f&&dis[edge[i].v]>dis[p]+edge[i].w) { dis[edge[i].v]=dis[p]+edge[i].w; Pre[edge[i].v]=i; if(!vis[edge[i].v]) vis[edge[i].v]=1,q.push(edge[i].v); } } } return dis[T]<INF; } int F() { int nowflow=INF; for(int now=T;now!=S;now=edge[Pre[now]].u) nowflow=min(nowflow,edge[Pre[now]].f); for(int now=T;now!=S;now=edge[Pre[now]].u) edge[Pre[now]].f-=nowflow, edge[Pre[now]^1].f+=nowflow; return nowflow*dis[T]; } void MCMF() { int ans=0; while(SPFA()) ans+=F(); printf("%d\n",abs(ans)); } int belong[MAXN][MAXN]; int main() { #ifdef WIN32 freopen("a.in","r",stdin); #endif memset(head,-1,sizeof(head)); int a,b,P,Q; scanf("%d%d",&a,&b); scanf("%d%d",&P,&Q); P++;Q++; S=437,T=438; for(int i=1;i<=P;i++) for(int j=1;j<=Q;j++) belong[i][j]=(i-1)*Q+j; for(int i=1;i<=P;i++) { for(int j=1;j<=Q-1;j++) { int x; scanf("%d",&x); AddEdge(belong[i][j],belong[i][j+1],-x,1); AddEdge(belong[i][j],belong[i][j+1],0,INF); } } for(int j=1;j<=Q;j++) { for(int i=1;i<=P-1;i++) { int x; scanf("%d",&x); AddEdge(belong[i][j],belong[i+1][j],-x,1); AddEdge(belong[i][j],belong[i+1][j],0,INF); } } for(int i=1;i<=a;i++) { int num,x,y; scanf("%d%d%d",&num,&x,&y); AddEdge(S,belong[x+1][y+1],0,num); } for(int i=1;i<=b;i++) { int num,x,y; scanf("%d%d%d",&num,&x,&y); AddEdge(belong[x+1][y+1],T,0,num); } MCMF(); return 0; }
洛谷P4012 深海機器人問題(費用流)