網絡流24題(二十)
二十、深海機器人問題
題目描述
深海資源考察探險隊的潛艇将到達深海的海底進行科學考察。
潛艇内有多個深海機器人。潛艇到達深海海底後,深海機器人将離開潛艇向預定目标移動。
深海機器人在移動中還必須沿途采集海底生物标本。沿途生物标本由最先遇到它的深海機器人完成采集。
每條預定路徑上的生物标本的價值是已知的,而且生物标本隻能被采集一次。
本題限定深海機器人隻能從其出發位置沿着向北或向東的方向移動,而且多個深海機器人可以在同一時間占據同一位置。
用一個\(P\times Q\) 網格表示深海機器人的可移動位置。西南角的坐标為 \((0,0)\),東北角的坐标為 \((Q,P)\) 。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CM2MzNzI2M4MzM5EmY1U2NxYzXzMjMwcTMxMzLcBTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL4M3Lc9CX6MHc0RHaiojIsJye.png)
給定每個深海機器人的出發位置和目标位置,以及每條網格邊上生物标本的價值。
計算深海機器人的最優移動方案, 使深海機器人到達目的地後,采集到的生物标本的總價值最高。
輸入格式
檔案的第 1 行為深海機器人的出發位置數 a,和目的地數 b 。
第 2 行為 P 和 Q 的值。
接下來的 P+1 行,每行有 Q 個正整數,表示向東移動路徑上生物标本的價值,行資料依從南到北方向排列。
再接下來的 Q+1 行,每行有 P 個正整數,表示向北移動路徑上生物标本的價值,行資料依從西到東方向排列。
接下來的 行,每行有 3 個正整數 k,x,y,表示有 k 個深海機器人從 (x,y) 位置坐标出發。
再接下來的 b 行,每行有 3 個正整數 r,x,y ,表示有 r 個深海機器人可選擇 (x,y) 位置坐标作為目的地。
輸出格式
題解
模型
建圖
代碼
#include <iostream>
#include <queue>
#include <map>
#define ll long long
const ll N = 5e3+50,M = 5e4+50;
const ll inf = 0x3f3f3f3f;
using namespace std;
ll head[N],cnt = 1;
//将EK的bfs變為spfa
struct Edge{
ll to,w,cost,nxt;
}edge[M*2];
void add(ll u,ll v,ll w,ll c){
edge[++cnt] = {v,w,c,head[u]};
head[u] = cnt;
}
void add2(ll u,ll v,ll w,ll cost){
add(u,v,w,cost);
add(v,u,0,-cost);
}
ll s,t,dis[N],cur[N];
bool inq[N],vis[N];
queue<ll>Q;
bool spfa(){
while(!Q.empty()) Q.pop();
copy(head,head+N,cur);
fill(dis,dis+N,inf);
dis[s] = 0;
Q.push(s);
while(!Q.empty()){
ll p = Q.front();
Q.pop();
inq[p] = false;
for(ll e = head[p];e;e = edge[e].nxt){
ll to = edge[e].to,vol = edge[e].w;
if(vol > 0 && dis[to]>dis[p]+edge[e].cost){
dis[to] = dis[p] + edge[e].cost;
if(!inq[to]){
Q.push(to);
inq[to] = true;
}
}
}
}
return dis[t] != inf;
}
ll dfs(ll p = s,ll flow = inf){
if(p == t) return flow;
vis[p] = true;
ll rmn = flow;
for(ll eg = cur[p];eg && rmn;eg = edge[eg].nxt){
cur[p] = eg;
ll to = edge[eg].to,vol = edge[eg].w;
if(vol > 0 && !vis[to]&&dis[to] == dis[p]+edge[eg].cost){
ll c = dfs(to,min(vol,rmn));
rmn -= c;
edge[eg].w -= c;
edge[eg^1].w += c;
}
}
vis[p] = false;
return flow-rmn;
}
ll maxflow = 0,mincost = 0;
void dinic(){
while(spfa()){
ll flow = dfs();
maxflow += flow;
mincost += dis[t]*flow;
}
}
ll a,b,p,q;
map<pair<ll,ll>,ll>ma;
int main() {
ios::sync_with_stdio(false);
cin>>a>>b>>p>>q;
ll cnt0 = 0;
for(ll i = 0;i <= p;i++){
for(ll j = 0;j <= q;j++){
ma[{i,j}] = ++cnt0;
}
}
for(ll i = 0;i <= p;i++){
for(ll j = 1;j <= q;j++){
ll x;cin>>x;
add2(ma[{i,j-1}],ma[{i,j}],inf,0);
add2(ma[{i,j-1}],ma[{i,j}],1,-1*x);
}
}
for(ll j = 0;j <= q;j++){
for(ll i = 1;i <= p;i++){
ll x;cin>>x;
add2(ma[{i-1,j}],ma[{i,j}],inf,0);
add2(ma[{i-1,j}],ma[{i,j}],1,-1*x);
}
}
s = 0,t = cnt0+1;
for(ll i = 1;i <= a;i++){
ll k,x,y;cin>>k>>x>>y;
add2(s,ma[{x,y}],k,0);
}
for(ll i = 1;i <= b;i++){
ll k,x,y;cin>>k>>x>>y;
add2(ma[{x,y}],t,k,0);
}
dinic();
cout<<-1*mincost<<endl;
return 0;
}