uva 10201 dp油费问题

来源:互联网 发布:sql清除挂起工具 编辑:程序博客网 时间:2024/06/03 02:53

题意:

你要租一辆车去一个大城市(搞一个大新闻),这辆车的油桶可以装200L油,开始的时候这辆车只满了一半的油(100L)。

现在给你目的地离此地的距离dis,然后依次给出距离此地d km的油站,每个油站的油有自己的价格。

假设每开1 km消耗1 L油。

要求到达终点时,油箱至少是有一半的油,并且在中途不没油的情况下使花费最小。


解析:

去年做这题的时候参考了别人的代码。

好像是输入和输出都有点坑。详细理解DP的过程。

开始的时候预处理先抠掉超出终点的点。

dp[ n ] [ d ] 表示在第n个加油站,油箱里有d升油时的最小花费。

初始条件是dp[0] [100] = 0,在出发点并且油量为100。

然后枚举每个起点,从前一点到达这个起点需要油箱里至少有w = d[ i ] - d[ i - 1] 升油。

因此,若不在目前这个点加油,这点的花费是dp[i][j] = dp[i - 1][j + w] ;

若在此点加油,枚举加多少油,因此花费为 dp[i][j] = min(dp[i][j], dp[i - 1][j - k + w] + k * p[i])。

因为有可能最后一个点不像样例那样在终点处,所以若终点与最后一个点的距离大于100,则即使在最后那个加油站加满200L油也不能满足最后有半桶油;

若dp[n][100 + dis - d[n]] == inf,也是无法到达终点的。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = 4 * atan(1.0);const double ee = exp(1.0);const int maxd = 200 + 10;const int maxn = 100 + 10;int dp[maxn][maxd];int d[maxn], p[maxn];int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    char s[100];    int ncase;    gets(s);    sscanf(s, "%d", &ncase);    gets(s);    while (ncase--)    {        memset(d, 0, sizeof(d));        int dis;        gets(s);        sscanf(s, "%d", &dis);        d[0] = 0;        int n = 0;        while (gets(s) != NULL)        {            if (s[0] == '\0')                break;            ++n;            sscanf(s, "%d %d", &d[n], &p[n]);            //cout << d[n] <<" " << p[n] <<endl;            if (d[n] > dis)                --n;        }        memset(dp, inf, sizeof(dp));        dp[0][100] = 0;        for (int i = 1; i <= n; i++)        {            int w = d[i] - d[i - 1];            for (int j = 0; j + w <= 200; j++)//not use i                if (dp[i - 1][j + w] != inf)                    dp[i][j] = dp[i - 1][j + w];            for (int j = 0; j <= 200; j++)//use i add k L oil            {                for (int k = 0; k <= j; k++)                {                    if (j - k + w <= 200 && dp[i - 1][j - k + w] != inf)                        dp[i][j] = min(dp[i][j], dp[i - 1][j - k + w] + k * p[i]);                }            }        }        ///make sure final oil >= 100        if (100 < dis - d[n] || dp[n][100 + dis - d[n]] == inf)        {            printf("Impossible\n");        }        else        {            printf("%d\n", dp[n][100 + dis - d[n]]);        }        if (ncase)            printf("\n");    }    return 0;}



0 0