nyoj-1216-整理图书-dp
整理图书
Time Limit: 3000MS Memory Limit: 65535K
描述
小明是图书鹳狸猿,他有很多很多的书堆在了一起摆在了架子上,每摞书是横着放的,而且每摞书是订好的是一个整体,不可分开,(可以想象架子是一条直线),但是这些书高度却参差不齐,小明有强迫症,看不得不整齐,所以他想让这些书的高度形成一个非降序列他才舒心,可是这些书是有序的,所以他只能把其中的一摞书和他相邻的书装订在一起形成一摞新的书,那么他最少的装订次数是多少呢
输入
多组测试数据,处理到文件结束每组数据开始有一个n(1<=n<=1000)表示有n摞书接下来一行是这n摞书的高度a[i],(1<=a<=10^5)(虽然这个高度有点扯淡)
输出
首先输出Case num : 表示第几组数据接下来对于每组数据输出最少的装订次数
样例输入
5
8 2 7 3 1
1
100
样例输出
Case 1: 3
Case 2: 0
提示
第一组样例:将后4本书装订在一起,共装订3次,组成8 13
第二组样例:只有一本书,无需装订
----------
思路:
用book[i]表示前i堆书总高度,maxh[i]表示前i堆书被整理后的倒数第一堆的高度(也就是被整理后最高的一堆书的高度),dp[i]表示前i堆书被整理后所需的最少装订次数
状态转移:
其中有个地方可以优化一下,先看下面:
对于i一定时,假设有k1, k2(属于k且k1 < k2)满足 "book[i] - book[k] >= maxh[k]"。
根据状态转移可知,存在kx,使得dp[k1] = dp[kx] + k1-kx-1,则dp[k2] <= dp[kx] + k2-kx-1 ( 因为 book[k2]-book[kx] > book[k1]-book[kx] >= maxh[kx],所以 dp[k2] = min(dp[k2], dp[kx] + k2-kx-1) )。
对于k1,因为dp[k1] = dp[kx] + k1-kx-1,所以dp[i] = min(dp[i], dp[k1] + i-k1-1) = min(dp[i], dp[kx] + i-kx-2);
对于k2,因为dp[k2] <= dp[kx] + k2-kx-1,所以dp[i] = min(dp[i], dp[k2] + i-k2-1) <= min(dp[i], dp[kx] + i-kx-2);
即当k2 > k1时,根据k2得到的dp[i]要小于根据k1得到的dp[i],而dp[i]又是求最小值,那么求得最大的kmax属于k使得“book[i] - book[k] >= maxh[k]“,那么根据kmax求得的dp[i]就是最小的。
优化后的状态转移:
最后附上代码: