【网络流24题】汽车加油行驶(分层图+最短路)

来源:互联网 发布:淘宝红包套现被处罚 编辑:程序博客网 时间:2024/05/07 03:49

传送门

    汽车加油行驶
    题意:给定网格,部分格点设有加油站,汽车驶至该格点必须加油。给定一辆车加满油的最大行驶距离,加一次油的花费,以及在任意点设置新油库的花费。求一辆满油车从左上角格点到右下角格点的最小花费。

I think

    根据汽车的剩余油量建立分层图。
    若油量不满,点< i,k>向点< i,top>连长度为A/A+C的边。
    若油量非空,非油库点< i,k>向点< j,k-1>连长度为0的边(j为i在网格图中右/下方的相临点),向点< j,k-1>连长度为B的边(j为i在网格图中左/上方的相临点).而满油油库点< i,k>向点< j,k-1>连长度为0的边(j为i在网格图中右/下方的相临点),向点< j,k-1>连长度为B的边(j为i在网格图中左/上方的相临点).(非满油油库点必然加油).

Code

#include<cstdio>#include<cstring>#include<queue>using namespace std;typedef pair<int,int> pii;const int sm = 11e4+10;const int sn = 10*sm;const int Inf = 0x3f3f3f3f;int N,K,A,B,C,tot,Ans;int to[sn],nxt[sn],hd[sm],c[sn];int vis[sm],dis[sm];int mp[11][102][102];int tag[102][102];int Min(int x,int y) { return x<y?x:y; }void Add(int u,int v,int w) {    to[++tot]=v,nxt[tot]=hd[u],hd[u]=tot,c[tot]=w;}bool chk(int u,int v) {    return (u>=1&&u<=N&&v>=1&&v<=N);}void Dijkstra(int s,int St) {    for(int i=1;i<=s;++i) dis[i]=Inf;    priority_queue<pii,vector<pii>,greater<pii> >Que;    Que.push(make_pair(dis[St]=0,St));    pii t;     while(!Que.empty()) {        t=Que.top(),Que.pop();        if(vis[t.second])continue;        vis[t.second]=1;        for(int i=hd[t.second];i;i=nxt[i])            if(!vis[to[i]]&&dis[to[i]]>dis[t.second]+c[i]) {                dis[to[i]]=dis[t.second]+c[i];                Que.push(make_pair(dis[to[i]],to[i]));            }    } }int main() {    int cnt=0,u;    scanf("%d%d%d%d%d",&N,&K,&A,&B,&C);    for(int k=0;k<=K;++k)        for(int i=1;i<=N;++i)            for(int j=1;j<=N;++j) {                if(k==0) scanf("%d",&tag[i][j]);//tag[i][j]==1该点设置了油库                mp[k][i][j]=++cnt;            }    for(int k=K;k>=0;--k)        for(int i=1;i<=N;++i)            for(int j=1;j<=N;++j) {                if(k!=K) //油量不满                    Add(mp[k][i][j],mp[K][i][j],A+C*(tag[i][j]^1));                if((!tag[i][j]&&k>0)||(k==K)) { //油量非空 //是油库且非满油 必然加油                    if(chk(i,j+1)) Add(mp[k][i][j],mp[k-1][i][j+1],0);                    if(chk(i+1,j)) Add(mp[k][i][j],mp[k-1][i+1][j],0);                    if(chk(i,j-1)) Add(mp[k][i][j],mp[k-1][i][j-1],B);                    if(chk(i-1,j)) Add(mp[k][i][j],mp[k-1][i-1][j],B);                }            }    Dijkstra(cnt,mp[K][1][1]);    Ans=Inf;    for(int i=0;i<=K;++i)        Ans=Min(Ans,dis[mp[i][N][N]]);    printf("%d\n",Ans);    return 0;}
原创粉丝点击