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;
}