P4009 汽车加油行驶问题
生活随笔
收集整理的這篇文章主要介紹了
P4009 汽车加油行驶问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述:
題解:
看了很多題解,無論什么解法都繞不開分層圖
在本題中加滿油的車每次可以移動K步,那么我們就可以建立一個K+1層的分層圖,表示汽車油量k的狀態(油量0…k),然后根據題目要求建圖
首先我們規定(k從1開始)第k層第i行第j列點編號為(k-1) * n * n + (i-1) * n + j
首先我們從第k層(i,j)建立一條邊到第k+1層(i,j),邊權為0,相當于車原地不動(其實這一步可有可無)
然后肯定是否到達油站來詳細分析:
當到達油站時,油會加滿,所以無論當前為哪一層都要指向第一層指向一個邊,邊權為a(即加油費)。然后從第一層的(i,j)向第二層的四個方向指向邊,因為當i和j減少時要化為b,所以指向(i-1,j)和(i,j-1)時邊權為b,另外兩個(i+1,j)和(i,j+1)邊權為0,當然要注意當前點是否在圖的邊緣,以防止越界
當沒到油站時,我們要向下一層的四個方向指向邊,然后我們要模擬建立油站的情況,該點所有層均要向第一層生成一個有向邊,邊權為建立油站的費用+加油的費用(即a+c)
然后跑最大流或者spfa都可以
代碼:
結合代碼分析分析
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std;const int INF=2e9;int n,k,p,b,c,cnt; int head[350005],dis[350005],q[900005]; bool vis[350005],oil; struct node{int next,v,dis; }a[900005];void add(int x1,int y1,int z1,int x2,int y2,int z2,int dis){int u=n*n*(z1-1)+(x1-1)*n+y1;int v=n*n*(z2-1)+(x2-1)*n+y2;a[++cnt]=(node){head[u],v,dis};head[u]=cnt; }void spfa(){for(int i=1;i<=n*n*(k+1);++i) dis[i]=INF;queue<int>q; //int hd=1,tl=1;int s=1;q.push(1);vis[s]=1;dis[1]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];i;i=a[i].next){if(dis[a[i].v]>dis[u]+a[i].dis){dis[a[i].v]=dis[u]+a[i].dis;if(!vis[a[i].v]){vis[a[i].v]=1;q.push(a[i].v);}}}} }int main(){scanf("%d%d%d%d%d",&n,&k,&p,&b,&c);for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){scanf("%d",&oil); // for(int l=1;l<=k;++l) // { // add(i,j,l,i,j,l+1,0);//走一步 // }if(oil){for(int l=2;l<=k+1;++l){add(i,j,l,i,j,1,p);}if(i<n) add(i,j,1,i+1,j,2,0);if(j<n) add(i,j,1,i,j+1,2,0);if(i>1) add(i,j,1,i-1,j,2,b);if(j>1) add(i,j,1,i,j-1,2,b);}else{for(int l=1;l<=k;++l){if(i<n) add(i,j,l,i+1,j,l+1,0);if(j<n) add(i,j,l,i,j+1,l+1,0);if(i>1) add(i,j,l,i-1,j,l+1,b);if(j>1) add(i,j,l,i,j-1,l+1,b);}for(int l=2;l<=k+1;++l){add(i,j,l,i,j,1,p+c);}}}}spfa();int ans=INF;for(int i=1;i<=k+1;++i) ans=min(ans,dis[n*n*i]);printf("%d\n",ans);return 0; }總結
以上是生活随笔為你收集整理的P4009 汽车加油行驶问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全麻可以戴隐形眼镜吗
- 下一篇: 带花树算法