HDU2059 龟兔赛跑(多决策的动态规划)

it2022-05-05  186

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2059

分析:

兔子跑完全部路程的时间是定值,主要看乌龟如何走完全程,且用时最短。用这个最短的时间和兔子的时间相比。

首先我们可以把起点和终点都当作充电站,这样一共就有n+2个充电站,特殊情况是起点的充电站给车子充满电是不需要时间的,所以这个情况需要特判一下就是dp[0] = 0. 我们最终的目标是到达终点处的充电站所需要的时间最短。

接下来我们来推到状态转移方程,假设当前充电站是 i ,然后我们要枚举 0 - i-1个充电站,每个充电站选择充还是不充表达式为:dp[i] = min(dp[i], dp[j]+x, dp[j]+y]) x表示在第j个充电站充完电然后开到 i 所用的时间(中途不再充电) y表示在第j个充电站不充电,直接开到 i 所用的时间

PS:当然这里dp[j]+y实际不必要考虑,因为你在j-1号充电站判断是不是要充电的时候已经把在J号充电站不充电的情况考虑进去了。所以加不加问题不大,思路都是正确的。加了更容易理解,如果你熟练了以后可以直接去掉。

code:

#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; const int INF = 0x3f3f3f3f; double dp[100+7]; int dis[100+7]; // 每个充电站到起点的距离 int main() { int l; while(scanf("%d", &l) != EOF) { int n, c, t; // 充电站的个数,充完电行驶的距离,充电所需时间 int vr, vt1, vt2; // 兔子的速度,骑车速度,脚蹬速度 scanf("%d %d %d", &n, &c, &t); scanf("%d %d %d", &vr, &vt1, &vt2); dis[0] = 0; dis[n+1] = l; for(int i=1; i<=n; i++) scanf("%d", &dis[i]); // memset(dp, 0x3f, sizeof(dp)); double类型不能用memset dp[0] = 0; for(int i=1; i<107; i++) dp[i] = INF; double tmp; for(int i=1; i<=n+1; i++) // 先枚举1到n+1个充电站 { for(int j=0; j<i; j++) // 枚举当前充电站之前的充电站 { int len = dis[i] - dis[j]; // 两个充电站之间的距离 if(len <= c) tmp = 1.0 * len / vt1; else tmp = 1.0 * c/vt1 + 1.0 * (len-c) / vt2; if(j != 0) // 因为考虑从的是在j充电站充电所以要加上充电的时间 tmp += t; dp[i] = min(dp[j]+tmp, dp[i]); } } double tr = 1.0 * l /vr; // 兔子所用时间 if(dp[n+1] > tr) printf("Good job,rabbit!\n"); else printf("What a pity rabbit!\n"); } return 0; }

 


最新回复(0)