日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P3356 火星探险问题

發(fā)布時間:2023/12/18 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P3356 火星探险问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

網(wǎng)絡(luò)流24題之一。

因為石頭只能取一次,因此容易想到用拆點限制。于是經(jīng)典的建圖,然后跑費用流。

這里說一下輸出路徑:用dfs隨著 有流過的邊 輸出即可,因為我的建圖點與點之間初始滿流是INF,所以比INF小的就是流過的邊(即有被流量),并且INF-現(xiàn)在的流量就是經(jīng)過次數(shù)。

那么每次找完方案并把流量++即可避免重復(fù)。

細(xì)節(jié)參考代碼:

#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=5000+10; const int M=50000+10; const int INF=0x3f3f3f3f; int n,m,s,t,bs,k,maxflow,mincost,mp[50][50]; struct edge{int nxt,to,cap,cost; }edges[M<<1]; int cnt=1,head[N],pre[N];void add_edge(int x,int y,int z,int c) {edges[++cnt].nxt=head[x]; edges[cnt].to=y; edges[cnt].cap=z; edges[cnt].cost=c; head[x]=cnt; }queue<int> q; int dis[N],lim[N]; bool inq[N]; bool spfa(int s,int t) {while (!q.empty()) q.pop();memset(dis,0x3f,sizeof(dis));memset(inq,0,sizeof(inq));dis[s]=0; inq[s]=1; lim[s]=INF; q.push(s);while (!q.empty()) {int x=q.front(); q.pop();for (int i=head[x];i;i=edges[i].nxt) {edge e=edges[i];if (e.cap && dis[x]+e.cost<dis[e.to]) {dis[e.to]=dis[x]+e.cost;pre[e.to]=i; //即e.to這個點是從i這條邊來的 lim[e.to]=min(lim[x],e.cap);if (!inq[e.to]) { q.push(e.to); inq[e.to]=1; }}}inq[x]=0;}return !(dis[t]==INF); }void MCMF() {maxflow=0; mincost=0;while (spfa(s,t)) {int now=t;maxflow+=lim[t];mincost+=lim[t]*dis[t];while (now!=s) {edges[pre[now]].cap-=lim[t];edges[pre[now]^1].cap+=lim[t];now=edges[pre[now]^1].to;}} }int id(int x,int y) { return (x-1)*m+y; }void dfs(int k,int x,int y) { //用dfs順序輸出方案 if (x==n && y==m) return;int u=id(x,y)+bs;for (int i=head[u];i;i=edges[i].nxt) {int v=edges[i].to;if (edges[i].cap<INF) { //初始流量為INF,小于INF即這條邊流過 if ((v-1)/m+1>x) printf("%d %d\n",k,0); else printf("%d %d\n",k,1);edges[i].cap++; //重點:是他的流量++,避免下次路徑重復(fù) dfs(k,(v-1)/m+1,(v-1)%m+1);return;}} }//P3356 火星探險問題 費用流+輸出路徑 int main() {cin>>k>>m>>n;for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&mp[i][j]);s=0; t=2*n*m+1; bs=n*m;for (int i=1;i<=n;i++)for (int j=1;j<=m;j++) {if (mp[i][j]==0) add_edge(id(i,j),id(i,j)+bs,INF,0),add_edge(id(i,j)+bs,id(i,j),0,0);if (mp[i][j]==1) add_edge(id(i,j),id(i,j)+bs,0,0),add_edge(id(i,j)+bs,id(i,j),0,0);if (mp[i][j]==2) {add_edge(id(i,j),id(i,j)+bs,1,-1); add_edge(id(i,j)+bs,id(i,j),0,1);add_edge(id(i,j),id(i,j)+bs,INF,0),add_edge(id(i,j)+bs,id(i,j),0,0);}if (i<n) add_edge(id(i,j)+bs,id(i+1,j),INF,0),add_edge(id(i+1,j),id(i,j)+bs,0,0);if (j<m) add_edge(id(i,j)+bs,id(i,j+1),INF,0),add_edge(id(i,j+1),id(i,j)+bs,0,0);}add_edge(s,id(1,1),k,0); add_edge(id(1,1),s,0,0);add_edge(id(n,m),t,k,0); add_edge(t,id(n,m),0,0);MCMF();for (int i=1;i<=maxflow;i++) dfs(i,1,1); //輸出總共有maxflow個方案 return 0; }

?

轉(zhuǎn)載于:https://www.cnblogs.com/clno1/p/10725932.html

總結(jié)

以上是生活随笔為你收集整理的P3356 火星探险问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。