【a302】&&【9306】贮油点问题

Time Limit: 1 second
Memory Limit: 2 MB

问题描述

一辆重型卡车欲穿过1000公里的沙漠,卡车耗油为1升/公里,卡车总载油能力为500公升。显然卡车装
一次油是过不了沙漠的。因此司机必须设法在沿途建立几个贮油点,使卡车能顺利穿越沙漠,试问
司机如何建立这些贮油点?每一贮油点应存多少汽油,才能使卡车以消耗最少汽油的代价通过沙漠?

编程计算及打印建立的贮油点序号,各贮油点距沙漠边沿出发的距离以及存油量。

No. distance(k.m.) oil(litre)

1 ×× ××

2 ×× ××

3 ×× ××


Input

Output

Sample Input

Sample Output

输出的距离和油量两部分场宽20,保留小数点后10位
No. Distance oil
0 0.0000000000 3836.4968364968
1 22.4331224331 3500.0000000000
2 60.8946608947 3000.0000000000
3 106.3492063492 2500.0000000000
4 161.9047619048 2000.0000000000
5 233.3333333333 1500.0000000000
6 333.3333333333 1000.0000000000
7 500.0000000000 500.0000000000
8 1000.0000000000 0.0000000000

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=a302

【题解】

从倒数第二个贮油点考虑;
因为我们从样例已经知道了d[8]=500,oil[8]=500;
这就表示我们到达这第8个贮油点的时候,刚好油耗完了;然后第8个点刚好有500L的油,则再加上去就可以在终点处耗完所有的油且到达终点了;(严格意义来说是,我们到第8个贮油点的时候,车上还有油,但不是恰好500L,要加上第8个贮油点的油才是500L,这个情况可以看成是我们把车上剩余的油全部倒在第8个贮油点,然后第8个贮油点就为500L的油了,然后再把500L的油加到车上。。。没错就是这样,我不是在卖萌、)
那么我们在第7个贮油点要多少油呢?显然我们得让贮油点7的储油量大于500;因为我们在第7和第8个贮油点之间来回走的时候就已经耗掉一点油了,恰好500升是肯定不够的;再考虑一下来回走的过程;则我们肯定最少要1000升的油;
这里写图片描述
如图所示,我们从第7个点满载两次出去到第8个点,然后再空载一次回来(红线);
显然。我们在1000升油中有500升是要放在第8个点的;
则另外500升就是在路途中消耗掉的;即从7->8然后从8->7再从7->8;也即3*s;
这样3*s=500升;则s=500/3;
这样我们就确定了贮油点7到贮油点8的距离;
可以想见;其实我们不一定要1000升的汽油放在贮油点7;
实际上800升也可以;
那样有500升是运到了贮油点8;则300升用于路上的消耗;
则3*s=300;则s=100;但是这样并不利于后面的递推;所以我们取个整数500;即第7个贮油点放1000升的油;
我再模拟下第6个点到第7个点的过程;
因为第7个点要1000升的油:
所以第6个点我们就假设要1500升的油;
还是一样;
这里写图片描述
我们因为路上会有损耗,所以不可能只在第6个点贮1000升的油;
选择1500是一个合理的数字;
则我们要往第7个点运3次油;如上图;
可以看到一共有5个箭头;则这5个箭头是在路上消耗掉的油;
则5*s=(1500-1000)则s=100;
所以第6个贮油点和第7个贮油点之间的距离为100km;

以此类推;
我们到了起点前的一个点d[1]的时候;
通过样例看到距离起点d[1]= 22.4331224331;oil[1]=3500;
则要从起点0运3500升的油在1号点贮存,需要在0号节点放多余3500升的油才行。
那么要多少油呢;
显然3500升;运7次是不够的;因为路上会有损耗;则需要运八次;
如下图;
这里写图片描述
则耗损的油量为d[1]*15==336.4968364968
然后再加上需要放在1号点的3500升油;
咋1号点需要放3836.4968364968油;
(每次从0到1后,只留回来的油量,剩余的全都放在1号贮油点;当然最后一次(即第8次从0到1的时候,就不用再放下油了,此时车上的油加上1号贮油点在前7次存下的油量恰好为3500,也就是说第8次到1号贮油点的时候1号贮油点还不是3500升油,要加上车上剩余的油才是3500升);

【完整代码】

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

void rel(LL &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t) && t!='-') t = getchar();
    LL sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

void rei(int &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t)&&t!='-') t = getchar();
    int sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

const int MAXN = 20;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
double d[MAXN];
double oil[MAXN];

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    d[1] = 1000;oil[1] = 0;
    d[2] = 500;oil[2] = 500;
    int i=2;
    double now = 500.0;
    while (true)
    {
        oil[i+1] = oil[i]+500;
        double dis = 2*i-1;
        dis = 500.0/dis;
        if (now-dis<0)
            break;
        i++;
        now-=dis;
        d[i] = now;
    }
    double dis = 2*i-1;
    i++;
    d[i] = 0;oil[i] = oil[i-1]+dis*now;
    puts("No.          Distance                 oil");
    rep2(j,i,1)
        printf("%d%20.10lf%20.10lf\n",i-j,d[j],oil[j]);
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(245)  评论(0编辑  收藏  举报