• [网络流24题] 汽车加油行驶问题


    题目链接:戳我

    分层图最短路问题。

    我们设(dp[i][k])表示节点为i,现在还有k条边可以走的状态。然后跑一个最短路就行了。因为是不定项更新,所以考虑spfa。

    注意到了加油站是强制消费。然后分向上下左右四个方向走和原地建加油站五种情况来讨论。

    注意最后更新答案的时候k==0不要忘了考虑!!(要不然就会像我一样WA掉一个点)

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define MAXN 100010
    using namespace std;
    
    int n,k,a,b,c,tot,edge_number,ans=2147483647;
    int m[MAXN],dp[MAXN][20],id[210][210],done[MAXN][20],head[MAXN*110];
    struct Node{int u,d;};
    struct Edge{int nxt,to,dis;}edge[MAXN*110];
    
    inline void add(int from,int to,int dis)
    {
        edge[++edge_number].nxt=head[from];
        edge[edge_number].to=to;
        edge[edge_number].dis=dis;
        head[from]=edge_number;
    }
    
    inline void solve()
    {
        queue<Node>q;
        memset(dp,0x3f,sizeof(dp));
        q.push((Node){id[1][1],k});
        dp[id[1][1]][k]=0;
        done[id[1][1]][k]=1;
        while(!q.empty())
        {
            int u=q.front().u,d=q.front().d;
            q.pop();done[u][d]=0;
            if(d!=0)
            {
                for(int i=head[u];i;i=edge[i].nxt)
                {
                    int v=edge[i].to,yu=d-1,cur_dis=dp[u][d]+edge[i].dis;
                    if(m[v]==1) yu=k,cur_dis+=a;
                    if(cur_dis<dp[v][yu])
                    {
                        dp[v][yu]=cur_dis;
                        if(!done[v][yu])
                            q.push((Node){v,yu}),done[v][yu]=1;
                    }
                }
            }
            int cur_dis=dp[u][d]+c+a;
            if(m[u]==1) cur_dis-=c;
            if(cur_dis<dp[u][k])
            {
                dp[u][k]=cur_dis;
                if(!done[u][k])
                    q.push((Node){u,k}),done[u][k]=1;
            }
        }
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d%d%d",&n,&k,&a,&b,&c);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                id[i][j]=++tot,scanf("%d",&m[id[i][j]]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i!=1) add(id[i][j],id[i-1][j],b);
                if(j!=1) add(id[i][j],id[i][j-1],b);
                if(i!=n) add(id[i][j],id[i+1][j],0);
                if(j!=n) add(id[i][j],id[i][j+1],0);
            }
        }
        solve();
        for(int i=0;i<=k;i++) ans=min(ans,dp[id[n][n]][i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    找到IOS中的闪退日志
    day10-单元测试用例
    1、MySQL索引优化分析
    大话处理器-第2章-初识处理器
    sunset: dusk
    CK: 00
    My File Server: 1
    [luogu 5049] 旅行(数据加强版)
    [luogu p1081] 开车旅行
    [luogu p1613] 跑路
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10525596.html
Copyright © 2020-2023  润新知