生活随笔
收集整理的這篇文章主要介紹了
[网络流24题] 洛谷P3356 火星探险问题 费用流
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
和深海機(jī)器人問(wèn)題類(lèi)似。
給出P×QP×QP×Q的圖,P,Q≤35P,Q\leq35P,Q≤35。一些點(diǎn)是可以通行的,一些點(diǎn)是障礙,另外一些點(diǎn)則代表自己是礦產(chǎn),每個(gè)礦產(chǎn)只會(huì)被拿走一次。現(xiàn)在有n≤35n\leq35n≤35個(gè)機(jī)器人,他們從(1,1)(1,1)(1,1)出發(fā)走到(P,Q)(P,Q)(P,Q),輸出拿走最多礦產(chǎn)的方案。
和深海機(jī)器人類(lèi)似的做法,區(qū)別在于這里需要拆點(diǎn)。對(duì)于障礙點(diǎn)的流量為000,非障礙點(diǎn)都連無(wú)限流量和000的費(fèi)用。如果有礦產(chǎn)則連上111流量和礦產(chǎn)價(jià)值的費(fèi)用。
先求出能拿走多少礦產(chǎn)。然后輸出每次的路徑,從(1,1)(1,1)(1,1)出發(fā),記錄每條邊被用的次數(shù),反向邊的流量就是這條邊走過(guò)的流量,然后搜索打印路徑。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=40;
int len=0;
int a[N][N],mp[N][N],cnt=0;
int ans[140];
namespace MCMF {const int N=1e4,M=2e5;int tot=-1,n,S,T; int front[N],pre[N],lst[N];ll flow[N],dis[N];bool inq[N];struct edge{ int v,nxt;ll c,w; }e[2*M];int used[2*M]; void init() {tot=-1;for(int i=1;i<=n;i++) front[i]=-1;}void add(int u,int v,ll c,ll w) {e[++tot].v=v,e[tot].w=w,e[tot].c=c,e[tot].nxt=front[u],front[u]=tot;e[++tot].v=u,e[tot].w=-w,e[tot].c=0,e[tot].nxt=front[v],front[v]=tot;}void reset() {pre[T]=-1;for(int i=1;i<=n;i++) dis[i]=flow[i]=inf;for(int i=1;i<=n;i++) inq[i]=0;}bool spfa() {reset();queue<int> q;q.push(S);inq[S]=1;dis[S]=0;while(!q.empty()) {int u=q.front();q.pop();inq[u]=0;for(int i=front[u];i!=-1;i=e[i].nxt) {int v=e[i].v;if(e[i].c>0) {if(dis[v]>dis[u]+e[i].w) {dis[v]=dis[u]+e[i].w;flow[v]=min(flow[u],e[i].c);pre[v]=u,lst[v]=i;if(!inq[v]) {inq[v]=1;q.push(v);}}}}}return pre[T]!=-1?1:0; }pair<ll,ll> solve() {ll maxflow=0,mincost=0;while(spfa()) {int cur=T;maxflow+=flow[T];mincost+=flow[T]*dis[T];while(cur!=S) {e[lst[cur]].c-=flow[T];e[lst[cur]^1].c+=flow[T];cur=pre[cur];}}return make_pair(maxflow,mincost);} void dfs(int x,int y) {int now=mp[x][y]+cnt;int dow=mp[x+1][y];int rig=mp[x][y+1];for(int i=front[now];i!=-1;i=e[i].nxt) {if(used[i]>=e[i^1].c) continue;if(e[i].v==dow) {++used[i];ans[++len]=0;dfs(x+1,y);return;}if(e[i].v==rig) {++used[i];ans[++len]=1;dfs(x,y+1);return;}}}
}
int main() {int n;int P,Q;scanf("%d%d%d",&n,&P,&Q);MCMF::n=2*P*Q+2;int S=2*P*Q+1;int T=2*P*Q+2;MCMF::S=S;MCMF::T=T;MCMF::init();for(int i=1;i<=Q;i++) {for(int j=1;j<=P;j++) { scanf("%d",&a[i][j]);mp[i][j]=++cnt;}}MCMF::add(S,1,n,0);MCMF::add(2*cnt,T,n,0);for(int i=1;i<=Q;i++) {for(int j=1;j<=P;j++) {if(a[i][j]!=1) MCMF::add(mp[i][j],mp[i][j]+cnt,1e9,0); if(a[i][j]==2) MCMF::add(mp[i][j],mp[i][j]+cnt,1,-1);}}for(int i=1;i<=Q;i++) {for(int j=1;j<=P;j++) { if(i<Q) MCMF::add(mp[i][j]+cnt,mp[i+1][j],1e9,0);if(j<P) MCMF::add(mp[i][j]+cnt,mp[i][j+1],1e9,0);}}int flow=-MCMF::solve().second;for(int i=1;i<=flow;i++) {len=0;MCMF::dfs(1,1);for(int j=1;j<=len;j++)printf("%d %d\n",i,ans[j]);}return 0;
}
總結(jié)
以上是生活随笔為你收集整理的[网络流24题] 洛谷P3356 火星探险问题 费用流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。