NOIP 1999 旅行家的预算 解题报告

  最开始写的伪代码如下:

寻找当前油量能到达的最便宜的加油站
  如果找到了,那就开过去加油。
  如果找不到, 那就寻找最近的比本站便宜的站点
    找到的话就加油刚好开过去
    找不到的话就寻找次优站点,充满油开过去
      如果找不到任何站点,那就输出No Solution

  但是发现可以优化结构,就又写了一个:

寻找距离当前站最近的比当前站便宜的站点
  如果找到了,油量够就直接开过去,油量不够就冲到刚好可以开过去
  如果找不到,就到前面找一个充满油量能到得了的最便宜的站点,充满油开过去。
  如果加满油找不到任何站点,那就输出No Solution

  代码如下:

#include <stdio.h>
#include <stdlib.h>
struct dot{
	double dis, p;
}dots[100001];
double have = 0, used = 0;
double d1, c, d2, p;
int place = 0;

int com(const void *a, const void *b)
{
	struct dot i = *(struct dot *)a, j = *(struct dot *)b;
	return i.dis - j.dis;
}

void driveto(int id)
{
	place = id;
}

int main(int argc, char **argv)
{
	int i;
	int n, id;
	double small;
	scanf("%lf%lf%lf%lf%d", &d1, &c, &d2, &p, &n);
	dots[0].p = p;
	dots[n + 1].dis = d1;
	for(i = 1; i <= n; i++){
		scanf("%lf%lf", &dots[i].dis, &dots[i].p);
	}
	qsort(dots, n + 2, sizeof(struct dot), com);
	while(dots[place].dis < d1){
		id = -1;
		for(i = place + 1; i <= n + 1; i++){
			if(dots[place].dis + c * d2 >= dots[i].dis){
				if(dots[i].p <= dots[place].p){
					id = i;
					break;
				}
			}else{
				break;
			}
		}
		if(i == place + 1 && id == -1){
			printf("No Solution\n");
			return 0;
		}
		if(id != -1){
			if(dots[place].dis + have * d2 >= dots[id].dis){
				have -= (dots[id].dis - dots[place].dis) / d2;
			}else{
				used += ((dots[id].dis - dots[place].dis) / d2 - have) * dots[place].p;
				have = 0;
			}
		}else{
			small = 100000000;
			id = -1;
			for(i = place + 1; i <= n + 1; i++){
				if(dots[place].dis + c * d2 >= dots[i].dis){
					if(small >= dots[i].p){
						small = dots[i].p;
						id = i;
					}
				}else{
					break;
				}
			}
			used += (c - have) * dots[place].p;
			have = c;
			have -= (dots[id].dis - dots[place].dis) / d2;
		}
		place = id;
	}
	printf("%.2lf\n", used);
	return 0;
}

转载于:https://www.cnblogs.com/yylogo/archive/2011/07/30/NOIP-1999-2.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值