• [网络流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;
    }
    
  • 相关阅读:
    WPF通过不透明蒙板切割显示子控件
    WPF图片,DataGrid等实现圆角
    今天是2015年1月5日
    控制反转&依赖注入
    如何提高sql查询性能到达优化程序的目的
    handle句柄
    winform加快窗体加载速度
    winform窗体自适应大小
    快速整理代码(c#)
    IC卡、ID卡、M1卡、射频卡的区别是什么(射频卡是种通信技术)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10525596.html
Copyright © 2020-2023  润新知