zoukankan      html  css  js  c++  java
  • 【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
    ",i-j,d[j],oil[j]);
        return 0;
    }
    
  • 相关阅读:
    POJ 2236 Wireless Network(并查集)
    POJ 2010 Moo University
    POJ 3614 Sunscreen(贪心,区间单点匹配)
    POJ 2184 Cow Exhibition(背包)
    POJ 1631 Bridging signals(LIS的等价表述)
    POJ 3181 Dollar Dayz(递推,两个long long)
    POJ 3046 Ant Counting(递推,和号优化)
    POJ 3280 Cheapest Palindrome(区间dp)
    POJ 3616 Milking Time(dp)
    POJ 2385 Apple Catching(01背包)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626897.html
Copyright © 2011-2022 走看看