Full Tank? POJ - 3635(dijkstra)

题意:传送门
题解:考虑每个状态,当前所在城市和所剩余的油量,起始状态为 ( s , 0 ) (s,0) (s,0),拓展到新的状态有 ( c i t y , f u e l + 1 ) (city,fuel+1) (city,fuel+1),表示在该城市再添加一升油,第二种就是油量足够跑到下一个点上,就转化成一个最短路问题了。
c o d e : code: code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int N=1e3+5;
const int C=1e2+5;
const int M=2e4+5;
int n,m,u,v,d,q,c,s,e,dist[N][C],price[N];
struct edge{
    int u,v,w,next;
};
edge edges[M];
int head[N],tot;
void init()
{
    memset(head,-1,sizeof head);
    tot=0;
}
void add_edges(int u,int v,int w)
{
    edges[tot].u=u;edges[tot].v=v;edges[tot].w=w;edges[tot].next=head[u];head[u]=tot++;
    edges[tot].u=v;edges[tot].v=u;edges[tot].w=w;edges[tot].next=head[v];head[v]=tot++;
}
struct state{
    int cost,ver,fuel;
    state(int _cost=0,int _ver=0,int _fuel=0):cost(_cost),ver(_ver),fuel(_fuel){}
    bool operator < (const state &a)const {
        return cost>a.cost;
    }
};
bool st[N][C];
int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    memset(st,false,sizeof st);
    dist[s][0]=0;
    priority_queue<state>heap;
    heap.push(state(0,s,0));
    while(!heap.empty()){
        state t=heap.top();
        heap.pop();
        int cost=t.cost,ver=t.ver,fuel=t.fuel;
        if(st[ver][fuel]==true)continue;
        if(ver==e){
            return cost;
        }
        st[ver][fuel]=true;
        if(fuel+1<=c&&dist[ver][fuel+1]>dist[ver][fuel]+price[ver]){
            dist[ver][fuel+1]=dist[ver][fuel]+price[ver];
            heap.push(state(dist[ver][fuel+1],ver,fuel+1));
        }
        for(int i=head[ver];~i;i=edges[i].next){
            int v=edges[i].v,w=edges[i].w;

            if(w<=fuel&&dist[v][fuel-w]>dist[ver][fuel]){
                dist[v][fuel-w]=dist[ver][fuel];
                heap.push(state(dist[v][fuel-w],v,fuel-w));
            }
        }
    }
    return -1;
}
int main()
{
    n=read();m=read();
    for(int i=0;i<n;i++)price[i]=read();
    init();
    for(int i=0;i<m;i++){
        u=read();v=read();d=read();
        add_edges(u,v,d);
    }
    q=read();
    while(q--){
        c=read();s=read();e=read();
        int t=dijkstra();
        if(t==-1)puts("impossible");
        else printf("%d\n",t);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值