P4012 深海機器人問題 (費用流優先度)
阿新 • • 發佈:2018-12-18
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);
}