解题思路:
确定dp的含义
定义f[i][2],其中f[i][0]表示到达第i个杆子下方所需要的最小时间,f[i][1]表示到达第i个杆子传送门所需要的最少时间。
a[i]表示第i个杆子的传送门的位置
b[i]表示第i-1个传送门传送到第i个杆子的位置
x[i]表示第i个杆子的位置坐标
确定状态转移
第i个杆子的下方,即f[i][0],可以考虑两个方向到达,第一个方向为左侧到达,第二个方向为传送门到达。从左侧到达为f[i][0] = f[i-1][0] + (x[n]-x[n-1])*(1/1.0)。从上方到达则为f[i][0] = f[i-1][1] + b[i-1]*(1/1.3)。取其最小值为f[i][0],即f[i][0] = min( f[i-1][0] + (x[n]-x[n-1])*(1/1.0),f[i-1][1] + b[i-1]*(1/1.3))。第i个杆子传送门位置,即f[i][1],同样需要考虑两个方向到达,第一个方向为下侧到达,第二个方向是第i-1个传送门传送的位置到达。由于传送门的位置不定,因此可能出现在传送位置的上侧也可能出现在传送位置的下侧,由于速度不一,因此需要分开进行考虑。从下侧到达时f[i][1] = f[i][0] + a[i]*(1/0.7)。这里的f[i][0]已经在前面算出。从传送门位置到达为f[i-1][1] + (b[i-1]-a[i])*(1/1.3)或f[i-1][1] + (a[i]-b[i-1])*(1/0.7)具体取决于传送门的位置。取其最小值为f[i][1]。
可得状态转移方程f[i][0] = min( f[i-1][0] + (x[n]-x[n-1])*(1/1.0),f[i-1][1] + b[i-1]*(1/1.3))。
f[i][1] = min( f[i][0] + a[i]*(1/0.7),f[i-1][1] + (b[i-1]-a[i])*(1/1.3)) (传送门在下方的时候)
f[i][1] = min( f[i][0] + a[i]*(1/0.7),f[i-1][1] + (a[i]-b[i-1])*(1/0.7)) (传送门在上方的时候)
注意事项:
1.需要考虑传送门的位置,可以在上方也可以在下方,因为上爬,下滑速度不一。
2.需要使用double类型,float类型会缺失精度。
3.传送门在传送点下方的时候依然可以到达下方,即传送门不一定非要使用。
4.在n=1的时候需要单独进行考虑
参考代码:
#include<iostream> #include<stdio.h> using namespace std; const int MAXSIZE = 100010; int a[MAXSIZE],b[MAXSIZE]; int x[MAXSIZE]; double f[MAXSIZE][2];//上方最小值和下方最小值 double minfloat(double a,double b){ if(a>b)return b; else return a; } int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ cin>>x[i]; } for(int i=1;i<n;i++){ cin>>a[i]; cin>>b[i]; } f[1][0] = x[1]*1; f[1][1] = x[1]*1 + a[1]*(1/0.7); for(int i = 2;i<n;i++){ int dx = x[i] - x[i-1]; if(a[i]-b[i-1] > 0){ f[i][0] = minfloat(f[i-1][0] + (double)dx*(1/1.0),f[i-1][1] + b[i-1]*(1/1.3)); f[i][1] = minfloat(f[i][0] + a[i]*(1/0.7),f[i-1][1] + (a[i]-b[i-1])*(1/0.7)); }else{ f[i][0] = minfloat(f[i-1][0] + (double)dx*(1/1.0),f[i-1][1] + b[i-1]*(1/1.3)); f[i][1] = minfloat(f[i][0] + a[i]*(1/0.7),f[i-1][1] + (b[i-1]-a[i])*(1/1.3)); } } double minn; if(n!=1) minn = minfloat(f[n-1][0] + (x[n]-x[n-1])*(1/1.0),f[n-1][1] + b[n-1]*(1/1.3)); else minn = x[1]*(1/1.0); printf("%0.2lf",minn); return 0; }
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复