Ski Lift--动态规划,类似青蛙过河,没有状态压缩

http://www.rqnoj.cn/Problem_42.html


题目:Ski Lift

问题编号:42

题目描述

建造滑雪场的升降轨道。起点和终点的高度已知,x坐标分割成若干份,间隔为1,每一点都给出支架的高度。要选择尽可能少的支架顶端建立固定点,两个固定点之间用一条直钢轨连接,当然要求中间支架的高度都不能超过钢轨在那里的高度。而且两个相邻固定点之间的距离不能超过给定的K。
[输出说明]
可以选择第1、5、7、9、13个支架作为固定点。而且至少需要5个固定点。

输入格式

第一行是N和K,2<=N<=5000,1<=K<=N-1。
接下来N行,按顺序是支架的高度h,0<=h<=1000000000。

输出格式

一个整数,表示最少要选择几个固定点。第一个(起点)和最后一个(终点)一定是固定点。

样例输入

13 4
0
1
0
2
4
6
8
6
8
8
9
11
12

样例输出

5


一、思路
和青蛙过河很像,不过没有了状态压缩,第i处之前的i-1,i-k均为石子
一直没能理解这句话:
“当然要求中间支架的高度都不能超过钢轨在那里的高度。”

Ski Lift--动态规划,类似青蛙过河,没有状态压缩_第1张图片
就是说中间支架高度的不能凸出去,否则是没办法,放水平钢轨的

h[5001] 来保存每个点处支架的高度
f[5001]来表示第i个点处的最少固定点数
根据题意
f[i] = min(f[i-j] + 1)  ,其中1<=j<=k,并且i和i-j连结处的斜率小于  i 和 i-1,i-2...i-j+1处的任何一点的斜率,来保证中间支架高度不会超过钢轨

二、代码
1、读入n,k
2、读入每个点处高度,存于h[i]
3、二重循环动态规划求解
f[i] = min(f[i-j] + 1) 1<=j<=k
其中维护一个minK 来表示i-1, i-2, i-j+1 和 i处连结的最小斜率,这样省了一个三次循环

注意事项:
无论是否更新f[i], 每个点处的斜率都是要比较一次进行更新的
即:
//没有这个的时候,一个得分点错误
minK = minK>=currK ? currK : minK;

AC
代码如下:

#include 
#include 



int main()
{
	int n, k;
	int h[50001]={0}, f[5001]={0};//f[i] 第i处最少的固定点
	int i, j;
	//ifstream inFile("e:\\test.txt");

	//读入n,k
	cin>>n>>k;
	//inFile>>n>>k;
	//读入高度
	for (i=1; i<=n; i++)
	{
		cin>>h[i];
		//inFile>>h[i];
	}
	//动态规划求解
	f[1] = 1;
	for (i=2; i<=n; i++)
	{
		double minK = 1000000000.0;//最小斜率k
                int minDot = 50001;//最小固定点
		//向前查看k个位置
		for (j=1; j<=k&&i-j>=1; j++)
		{
			
			double currK = 1.0 * ( h[i] - h[i-j] ) / j;
                        //没有这个的时候,一个得分点错误
                        minK = minK>=currK ? currK : minK;
			if (minK>=currK && minDot>f[i-j]+1)
			{
				minDot = f[i-j]+1;
				//minK = currK;
			}
		}
		f[i] = minDot;
		//cout<


你可能感兴趣的:(算法)