1. 程式人生 > >P4012 深海機器人問題 (費用流優先度)

P4012 深海機器人問題 (費用流優先度)

P4012 深海機器人問題

題目連結: P4012

題意

在一個網格中給你一些機器人,要求只能向上走,或向左走,每一條邊都有一個寶藏,每個寶藏只能被拿一次。機器人只能在一些指定點開始放,在一些指定點收回來。問最多可以獲得多少財富?

思路

我一開始想的也是費用流,不過那個只能走一次的問題,我一直想不好。

其實只需要再建一條邊就好了,除了add_edge(u,v,1,-val) 再建一條邊add_edge(u,v,INF,0)即可,給圖一個可流的區間。

程式碼

#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <cctype> #include <cstdio> #include <string> #include <stack> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> #include <queue> #include <vector> #include <sstream> #include <memory>
#include <iostream> #include <algorithm> using namespace std; #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++) #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --) #define debug(x) cerr<<#x<<" = "<<(x)<<endl #define mmm(a,b) memset(a,b,sizeof(a)) #define
pb push_back
typedef double db; typedef long long ll; const int MAXN = (int)1e3+7; const int INF = (int)0x3f3f3f3f; struct edge{ int to,cap,cost,rev; edge(int to = 0,int cap = 0,int cost = 0,int rev = 0):to(to),cap(cap),cost(cost),rev(rev){} }; int N,M; vector<edge> G[MAXN]; int dist[MAXN]; int prevv[MAXN]; //圖的鄰接表 int preve[MAXN]; //最短路的前驅節點和對應的邊 void addedge(int from,int to,int cap,int cost) { G[from].pb(edge(to,cap,cost,(int)G[to].size())); G[to ].pb(edge(from,0,-cost,(int)G[from].size()-1)); } typedef pair<int,int> P; priority_queue<P,vector<P>, greater<P> > qu; int h[MAXN]; int min_cost_flow(int s,int t,int f){ int res = 0; fill(h+1,h+1+N,0); while(f > 0){ while (!qu.empty()) qu.pop(); mmm(dist,0x3f); dist[s] = 0; qu.push(P(0,s)); while(!qu.empty()){ P now = qu.top(); qu.pop(); if(dist[now.second] < now.first) continue; int v = now.second; rep(i,0,G[v].size()-1) { edge &e = G[v][i]; if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) { dist[e.to] = dist[v] + e.cost + h[v] - h[e.to]; prevv[e.to] = v; preve[e.to] = i; qu.push(P(dist[e.to],e.to)); } } } //cout << dist[t] << endl; if(dist[t] == INF) return res; rep(i,1,N) h[i] += dist[i]; int d = f; for(int v = t; v != s; v = prevv[v]) d = min(d,G[prevv[v]][preve[v]].cap); f -= d; res += d * h[t]; for(int v = t;v != s;v = prevv[v]){ edge &e = G[prevv[v]][preve[v]]; e.cap -= d; G[v][e.rev].cap += d; } } return res; } void init(){ rep(i,1,N) G[i].clear(); } int a,b,PP,Q; int east[20][20]; int north[20][20]; int main() { scanf("%d %d",&a,&b); scanf("%d %d",&PP,&Q); N = (PP+1)*(Q+1); int s = ++N; int t = ++N; int num = 1; rep(i,1,PP+1) { rep(j,1,Q) { scanf("%d",&east[i][j]); addedge(num,num+1,1,-east[i][j]); addedge(num,num+1,INF,0); num ++; } num ++; } num = 0; rep(i,1,Q+1) { int tmpNum = ++num; rep(j,1,PP) { scanf("%d",&north[i][j]); addedge(tmpNum,tmpNum+Q+1,1,-north[i][j]); addedge(tmpNum,tmpNum+Q+1,INF,0); tmpNum += Q+1; } } rep(i,1,a) { int y,x,k; scanf("%d %d %d",&k,&x,&y); y ++,x ++; int id = (x-1)*(Q+1)+y; addedge(s,id,k,0); } rep(i,1,b) { int y,x,k; scanf("%d %d %d",&k,&x,&y); y ++,x ++; int id = (x-1)*(Q+1)+y; addedge(id,t,k,0); } int res = -min_cost_flow(s,t,INF); printf("%d\n",res); }