蓝桥杯 蜗牛 动态规划
16.蜗牛 - 蓝桥云课https://www.lanqiao.cn/problems/4985/learning/?page=1&first_category_id=1&second_category_id=3&sort=difficulty&asc=1&tags=%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92,%E9%80%92%E6%8E%A8,01%E8%83%8C%E5%8C%85,%E5%8C%BA%E9%97%B4DP,%E6%95%B0%E4%BD%8DDP,%E6%96%9C%E7%8E%87%E4%BC%98%E5%8C%96,%E6%9C%9F%E6%9C%9BDP,%E6%A0%91%E5%BD%A2DP,%E7%8A%B6%E5%8E%8BDP,%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98,%E8%AE%B0%E5%BF%86%E5%8C%96%E6%90%9C%E7%B4%A2&tag_relation=union
一道DP题
要求求出从原点开始到第N根柱子(竹竿)的底部的最短时间
所以我们要设置一个DP数组 dp[i]表示到第i根柱子底部的最短时间
以到第三根柱子底部的最短时间为例子
我们发现有两种方法可以到达第三根柱子的底部
第一种,从出发点1 开始走第二根柱子的传送门,传送到第三根柱子的相应位置pre然后从pre走到第三根柱子底部;
第二种,从第二根柱子的底部直接过来第三根柱子的底部 ;
考虑第一种方法的原因在于 如果两根柱子离得非常远 比如距离为10000,而走传送门在柱子上移动的距离只有10,远小于直接走X轴
考虑第二种方法的原因在于 有可能两柱子离得非常近 比如在x轴的距离为1 ,传送门却非常高,比如传送门高度10000;因此直接从底下走过去更快
因此实际上我们需要计算出到第i根柱子的底部的最短时间,实际上需要到第i-1根柱子的传送门的最短时间,和到第i-1根柱子底部的最短时间两个数据
分别记作dp[i-1][0],dp[i-1][1]
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
int n;
struct node{double cur;double nxt;double pre;double x;
};
double dp[N][2];
node a[N];int main(){cin>>n;for(int i = 1 ; i<=n;i++){cin>>a[i].x ;}for(int i = 1;i<n;i++){cin>>a[i].cur ; //当前柱子的传送门位置 cin>>a[i].nxt ; //传送到下一根柱子的位置 a[i].pre = a[i-1].nxt ; //被上一根柱子传送过来的出口 }a[0].x = 0;a[0].cur = 0;a[n].cur = a[n-1].nxt ;a[n].pre = a[n-1].nxt ;dp[0][1] = 0;dp[0][0] = 1e8;for(int i = 1 ; i <= n;i++){double add1 ; //上个传送门传过来 再走到当前传送门 //传送门有可能在上一个柱子出口的上面 也可能在出口的下面 if(a[i].cur > a[i].pre ){add1 = (a[i].cur - a[i].pre)/((0.7)*1.0) ; }else if(a[i].cur <= a[i].pre ){add1 = (a[i].pre - a[i].cur)/((1.3)*1.0) ; }double timecur1 = dp[i-1][0] + add1; ///到上个柱子传送门的最短时间 + 被传送出来后走到当前柱子传送门的时间 double line11 = dp[i-1][1]; double line12 = a[i].x - a[i-1].x ; //右 double line13 = a[i].cur /((0.7)*1.0); //上 double timecur2 = line11 + line12 +line13 ;/// 在上个柱子底部的最短时间 + 走到第i根柱子再上传送门 dp[i][0] = min(timecur1,timecur2); //到当前柱子传送门最短时间 double timedown1 = dp[i-1][1] + a[i].x - a[i-1].x; //从上个柱子底直接走到这个柱子底部 double line22 = a[i].pre/((1.3)*1.0); //从传送门下到柱子底部 double timedown2 = dp[i-1][0] + line22;dp[i][1] = min(timedown1,timedown2);//到当前柱子底最短时间 }printf("%.2lf",dp[n][1]);return 0;
}