UVA-11367 Full Tank? (dijkstra)

题目大意:有n个加油站,每个加油站的油价已知,并且已知油箱的大小,问能否从起点走到终点,若能,找出最小油费。

题目分析:记得在做暴力搜索的时候做过这道题,不算难。但是这次是用dijkstra算法做的,时间复杂度不理想,差一点超时(1.9s,限制是2s)。用BFS做的话要快很多。

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))

const int INF=1<<30;
struct Node
{
    int u,k;
    Node(int _u,int _k):u(_u),k(_k){}
};
const int N=1005;
struct Edge
{
    int to,nxt,w;
};
Edge e[N*20];
int inq[N][105],dis[N][105],head[N],p[N],n,m,cnt;

void add(int u,int v,int w)
{
    e[cnt].to=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt++;
}

int dijkstra(int C,int s,int t)
{
    CL(inq,0);
    REP(i,0,n) REP(j,0,C+1) dis[i][j]=INF;
    queue<Node>q;
    q.push(Node(s,0));
    dis[s][0]=0;
    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        int u=top.u,k=top.k;
        inq[u][k]=0;
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(k>=e[i].w&&dis[v][k-e[i].w]>dis[u][k]){
                dis[v][k-e[i].w]=dis[u][k];
                if(!inq[v][k-e[i].w]){
                    inq[v][k-e[i].w]=1;
                    q.push(Node(v,k-e[i].w));
                }
            }
            if(k<C&&dis[u][k+1]>dis[u][k]+p[u]){
                dis[u][k+1]=dis[u][k]+p[u];
                if(!inq[u][k+1]){
                    inq[u][k+1]=1;
                    q.push(Node(u,k+1));
                }
            }
        }
    }
    int res=INF;
    REP(i,0,C+1) res=min(res,dis[t][i]);
    return res;
}

int main()
{
    int a,b,c,query;
    while(~scanf("%d%d",&n,&m)){
        cnt=0;
        CL(head,-1);
        REP(i,0,n) scanf("%d",p+i);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        scanf("%d",&query);
        while(query--)
        {
            scanf("%d%d%d",&a,&b,&c);
            int k=dijkstra(a,b,c);
            if(k==INF)
                printf("impossible\n");
            else
                printf("%d\n",k);
        }
    }
    return 0;
}

  

时间: 2024-08-02 14:48:29

UVA-11367 Full Tank? (dijkstra)的相关文章

uva 10986 Sending email (dijkstra)

uva 10986 Sending email "A new internet watchdog is creating a stir in Springfield. Mr. X, if that is his real name, has come up with a sensational scoop."Kent Brockman There are n SMTP servers connected by network cables. Each of the m cables c

uva 11374 Airport Express (Dijkstra)

 题意:在Iokh市中,机场快线是市民从市内去机场的首选交通工具.机场快线分为经济线和商业线两种,线路,速度和价钱都不同.你有一张商业线车票,可以做一站商业线,而其他时候只能乘坐经济线.假设换乘时间忽略不计,你的任务是找一条去机场最快的路线.. 分析:枚举商业线T(a,b),则总时间为f(a)+T(a,b)+g(b);f和g用两次dijkstra来计算,以S为起点的dijkstra和以E为起点的dijkstra: 注意:有可能只做慢车到达不了终点,这时必须做某站快车,如果按照坐慢车一定能到达

UVA 11367 - Full Tank?(最短路+DP)

UVA 11367 - Full Tank? 题目链接 题意:给定一个无向图,每个点有一个加油站,有一个油价,现在一辆车,每次询问要从起点s走到t,邮箱容量为c,问最小代价 思路:dijkstra算法,d数组多一个状态,表示当前油量即可 不过这题如果每次都把所有状态转移完,挺费时间的,卡着时间过的 后面改成每次1升1升加油去转移状态,效率会比较快,因为有很多无用状态可以省去 代码: #include <cstdio> #include <cstring> #include <

最短路径算法——迪杰斯特拉算法(Dijkstra)

图结构中应用的最多的就是最短路径的查找了,关于最短路径查找的算法主要有两种:迪杰斯特拉算法(Dijkstra)和Floyd算法. 其中迪杰斯特拉算法(Dijkstra)实现如下: 原理就是不断寻找当前的最优解: void main() { int V[Max][Max]={0,8,32,Infinity,Infinity, 12,0,16,15,Infinity, Infinity,29,0,Infinity,13, Infinity,21,Infinity,0,7, Infinity,Infi

hdu 1874(Dijkstra )

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1874 畅通工程续 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 27692    Accepted Submission(s): 10019 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路

UVA 618 - Doing Windows(数论)

题目链接:618 - Doing Windows 题意:给定一个大小不能变的屏幕,和四个大小可以变的窗口,变化要保持长宽比,问这四个窗口能不能调整后全部放下正好填满屏幕,不能重叠 思路:情况一共就几种:4个叠一起,3个叠一起+一个,2个和2个,一个和两个叠一起在一个,把这几种情况全判断了就可以了,判断过程利用gcd,lcm可以求边长. 代码: #include <stdio.h> #include <string.h> long long gcd(long long a, long

Uva 10404-Bachet&#39;s Game(博弈)

题目链接:点击打开链接 在DP专题里刷到的,看着像博弈就水过去了.. 题意:n件物品,两个人轮流取,每次取的数量必须为一个集合s(集合里肯定含有1)里的一个数字,最后不能取者输(即取走最后一件物品者胜). 思路:递推.设 w[i] 为有i件物品时的状态,w[i]=1代表先手必胜,w[i]=0代表先手必败.可以知道w[1]=1,递推生成所有状态. 可以知道对于一个状态,如果他的后继存在必败状态,则该状态为必胜状态:如果该状态的所有后继都为必胜状态,那么该状态为必败状态. #include <alg

poj1062昂贵的聘礼(Dijkstra**)

1 /* 2 题意: 物主有一个物品,价值为P,地位为L, 以及一系列的替代品Ti和该替代品所对应的"优惠"Vi 3 g[u][i] 表示的是u物品被i物品替换后的优惠价格!(u>0, i>0) 4 g[u][0]表示不用替换该物品的实际价格 ! 5 d[0]表示的是第一个物品经过一系列的物品替换之后的最少优惠价格! 6 7 思路:每当我们通过Dijkstra算法得到离源点(1)最近的距离的节点 p的时候(也就是1...pre[p], p)这条 8 路径上的物品互相替换后得

UVA 417 - Word Index(数论)

题意:417 - Word Index 题意:每个字符串按题目中那样去映射成一个数字,输入字符串,输出数字 思路:这题还是比较水的,由于一共只有83000多个数字,所以对应一个个数字去映射就可以了,注意字符串进位的情况处理即可 代码: #include <stdio.h> #include <string.h> #include <map> #include <string> using namespace std; char str[10]; map<