• poj 3635Full Tank?(dp+最短路变形)


    题目链接:http://poj.org/problem?id=3635

    题意:有n个城市,m条双向路。给出每个城市的油价,每条路需要耗费一定的油量。有q个询问,油箱的容量为c的车,从城市s走到e,求最少的加油价格。 

    思路:dp[i][j]表示到达城市 i 还剩 j 油量的最小花费。用优先队列(优先最小花费)更新,即变形的dijkstra,有两个操作,加油和过路。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int maxn=1100;
    const int maxm=21000;
    struct node{
        int u,v,w,nxt;
    }e[maxm];
    struct point{
        int id,cost,oil;
        bool operator <(const point a)const{
            return a.cost<cost;
        }
    };
    int dp[maxn][110],p[maxn];
    int h[maxn],vis[maxn][110];
    int n,m,k,st,ed,cnt,c;
    
    void add(int u,int v,int w)
    {
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
        e[cnt].nxt=h[u];
        h[u]=cnt++;
    }
    
    void bfs()
    {
        memset(dp,0x3f,sizeof(dp));
        memset(vis,0,sizeof(vis));
        priority_queue<point> q;
        q.push(point{st,0,0});
        dp[st][0]=0;
        while(!q.empty())
        {
            point t=q.top();q.pop();
            int u=t.id,cost=t.cost,o=t.oil;
            vis[u][o]=1;
            if(u==ed)
            {
                printf("%d
    ",cost);
                return ;
            }
            if(o+1<=c&&!vis[u][o+1]&&dp[u][o]+p[u]<dp[u][o+1])//加油 
            {
                dp[u][o+1]=dp[u][o]+p[u];
                q.push(point{u,dp[u][o+1],o+1});
            }
            for(int i=h[u];i!=-1;i=e[i].nxt)//过路 
            {
                int v=e[i].v;
                int w=e[i].w;
                if(o>=w&&!vis[v][o-w]&&dp[v][o-w]>cost)
                {
                    dp[v][o-w]=cost;
                    q.push(point{v,cost,o-w});
                }
            }
        }
        printf("impossible
    ");
    }
    
    int main()
    {
        int u,v,w;
        cnt=0;
        memset(h,-1,sizeof(h));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d",&p[i]);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        scanf("%d",&k);
        while(k--)
        {
            scanf("%d%d%d",&c,&st,&ed);
            bfs();
        }
        return 0;
    }
  • 相关阅读:
    sratookit
    转录组测序
    单菌基因组测序常见问题
    微生物测序样本准备方法总结
    Review:Microbiota, metagenome, microbiome傻傻分不清
    扩增子、宏基因组测序问题集锦
    扩增子图表解读8网络图:节点OTU或类Venn比较
    扩增子图片解读7三元图
    扩增子图表解读5火山图:差异OTU的数量及变化规律
    扩增子图表解读6韦恩图:比较组间共有和特有OTU或分类单元
  • 原文地址:https://www.cnblogs.com/xiongtao/p/11217520.html
Copyright © 2020-2023  润新知