[24ネットワークフロー問題車両の給油問題(層状のグラフ)

問題の意味

リンク

考え

偽のネットワークフロー

油は小さなKと一緒に、この状態に直接格納することができないので、原画像を階層化することができ、K + 1は、図のレイヤに分割され、それぞれ、油の電流量が0〜K

でもエッジ

  1. あなたはすぐに戻ってそれ以外の場合はB、0の値に行けばしても4つの方向への油の最初の完全なk層については、一歩を表し

  2. 非充填リザーバため、ガスステーションは、現在のポイント場合、k番目の層は、エッジ、Aの右側の値に対応する点唯一の点である燃料補給の間に表します

  3. リザーバ非充填のために、現在のノードがガソリンスタンドでない場合、それは次の層、同じものに対応する4つの方向に接続することができ、それはまた表し、k番目の層の対応点に接続された一の側、A + Cの重量を有します給油所の間で確立する(正しさのさえ側面が保証できるように、一度図のグリッド上の各ポイントので上がります)

  4. 最後に、点k + 1に対応するエンドポイントが会議点Tに接続され、右側が0であります

k番目の層、最短ラン、DIS [T]の始点からSは、答えであります

コード:

#include<bits/stdc++.h>
#define N 200005
#define M 2000005
using namespace std;
int n,k,A,B,C,s,t;
int a[105][105];
int dis[N];
bool vis[N];

struct Node
{
    int u,dis;
    bool operator < (const Node a)const
    {
        return a.dis<dis;
    }
};
struct Edge
{
    int next,to,dis;
}edge[M];int head[N],cnt;
void add_edge(int from,int to,int dis)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    edge[cnt].dis=dis;
    head[from]=cnt;
}
void dijkstra(int s)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    priority_queue<Node> q;
    q.push((Node){s,0});
    dis[s]=0;
    while(!q.empty())
    {
        int u=q.top().u;q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].dis)
            {
                dis[v]=dis[u]+edge[i].dis;
                if(!vis[v]) q.push((Node){v,dis[v]});
            }
        }
    }
}
int main()
{
    scanf("%d%d%d%d%d",&n,&k,&A,&B,&C);
    s=1;t=N-5;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            scanf("%d",&a[i][j]);
        //代码中i=0为满油层
    for(int i=0;i<=k;++i)
        for(int j=1;j<=n;++j)
            for(int p=1;p<=n;++p)
            {
                int id=(j-1)*n+p,step=n*n;
                if(!a[j][p]||!i)//不是加油站,可以向四周连边;或者满油位置 
                {
                    if(i!=k)//还有油 
                    {
                        if(p!=n) add_edge(step*i+id,step*(i+1)+id+1,0);//向右
                        if(p!=1) add_edge(step*i+id,step*(i+1)+id-1,B);//向左
                        if(j!=n) add_edge(step*i+id,step*(i+1)+id+n,0);//向下
                        if(j!=1) add_edge(step*i+id,step*(i+1)+id-n,B);//向上
                    }
                }
                if(a[j][p]&&i) add_edge(step*i+id,id,A);//加油站
                if(!a[j][p]&&i) add_edge(step*i+id,id,A+C);//新建加油站 
            }
    for(int i=0;i<=k;++i) add_edge(n*n*(i+1),t,0);//连终点 
    dijkstra(s);
    cout<<dis[t]<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/Chtholly/p/11325010.html