【最短路】汽车加油

1、汽车加油(oi.pas/cpp)

 

【问题描述】

一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。并证明算法能产生一个最优解。

对于给定的n和k个加油站位置,编程计算最少加油次数。

【数据输入】

第一行有2 个正整数n和 k(1<n<4000,1<m<1000),表示汽车加满油后可行驶n公里,且旅途中有k个加油站。接下来的1行中,有 k+1个的整数(每个整数不超过100),表示第 k个加油站与第k-1个加油站之间的距离。第0个加油站表示出发地,汽车已加满油。第k+1个加油站表示目的地。

【数据输出】

输出最少加油次数。如果无法到达目的地,则输出“No Solution”。

 

【输入样例】

7 7

1 2 3 4 5 1 6 6

 

【输出样例】

4


标程方法是贪心,不知道怎么搞的。

一个点到另外一个点有边的条件是加满油后两地之间距离小于等于n。边权为1.

然后求到终点的距离。


#include <cstdio>
#include <cstring>
#include <string>

bool map[1020][1020];
long sum[1020];
long d[1020];
long cost[1020];
long que[1000000];
bool inque[1020];
long n;
long L;

long getint()
{
    long rs=0;bool sgn=1;char tmp;
    do tmp = getchar();
    while (!isdigit(tmp)&&tmp-'-');
    if (tmp=='-'){tmp=getchar();sgn=0;}
    do rs=(rs<<3)+(rs<<1)+tmp-'0';
    while (isdigit(tmp=getchar()));
    return sgn?rs:-rs;
}

void make()
{
    for (long i=0;i<n;i++)
    {
        for (long j=i+1;j<n+1;j++)
        {
            if (sum[j] > sum[i]+L)
                break;
            map[i][j] = true;
        }
    }
}

void spfa()
{
    memset(cost,0x7f,sizeof cost);
    long l = 0;
    long r = 0;
    r ++;
    que[r] = 0;
    cost[0] = 0;
    inque[0] = true;
    while (l < r)
    {
        l ++;
        long u = que[l];
        inque[u] = false;
        for (long v=u+1;v<n+1;v++)
        {
            if (!map[u][v])
                break;
            if (cost[v] > cost[u] + 1)
            {
                cost[v] = cost[u] + 1;
                if (!inque[v])
                {
                    inque[v] = true;
                    r ++;
                    que[r] = v;
                }
            }
        }
    }
}

int main()
{
    freopen("oi.in","r",stdin);
    freopen("oi.out","w",stdout);
    L = getint();
    n = getint() + 1;
    for (long i=1;i<n+1;i++)
    {
        d[i] = getint();
        sum[i] = sum[i-1]+d[i];
    }
    make();
    spfa();
    if (cost[n] == 0x7f7f7f7f)
        printf("No Solution");
    else
        printf("%ld",cost[n]-1);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值