nyoj 1216——整理图书 CF 229D—— Towers——————【dp+贪心】
2015-07-30 21:09
363 查看
整理图书
时间限制:3000 ms | 内存限制:65535 KB难度:5
描述
小明是图书鹳狸猿,他有很多很多的书堆在了一起摆在了架子上,每摞书是横着放的,而且每摞书是订好的
是一个整体,不可分开,(可以想象架子是一条直线),但是这些书高度却参差不齐,小明有强迫症,看不得不整齐
所以他想让这些书的高度形成一个非降序列他才舒心,可是这些书是有序的,所以他只能把其中的一摞书和他相邻的书装订在一起
形成一摞新的书,那么他最少的装订次数是多少呢
输入多组测试数据,处理到文件结束
每组数据开始有一个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
第二组样例:只有一本书,无需装订解题思路:我们定义dp[i]表示将前i摞图书整理成非降序列时的最少步数。定义h[i]表示前i摞书的最高的书高。同时sum[i]来记录前i摞书的总高度。dp[i]=dp[j]+(i-j-1)。如果前j摞书中最高书高小于等于sum[i]-sum[j]。则判断是否将j--->i这么多摞书合并在一块儿是否比dp[i]更小,如果是,则更新dp[i],h[i]。为什么从i-1开始只要能找到更新dp[i]的就算是最优结果了?因为dp[j]已经是最优结果了,那么我在最优解的基础上找到最小的增量,那么dp[i]也肯定是最优解了。
#include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 5050; int a[maxn], sum[maxn], dp[maxn], h[maxn]; int main() { int n, cnt = 0; while ( scanf ( "%d", &n ) != EOF ) { memset ( sum, 0, sizeof ( sum ) ); for ( int i = 1; i <= n; i++ ) { scanf ( "%d", &a[i] ); h[i] = max ( h[i - 1], a[i] ); sum[i] = sum[i - 1] + a[i]; } memset ( dp, INF, sizeof ( dp ) ); dp[0] = 0; //当前0或1摞书非降序时需要最少装订次数为0 dp[1] = 0; for ( int i = 2; i <= n; i++ ) { for ( int j = i - 1; j >= 0; j-- ) { if ( h[j] <= sum[i] - sum[j] ) {//当前j个中最大高度大于等于从j到i的总书高,进行状态转移 if ( dp[i] > dp[j] + i - j - 1 ) { dp[i] = dp[j] + i - j - 1; //更新dp h[i] = sum[i] - sum[j]; //更新前i摞书中最高的书高高度 break; } } } } printf ("*Case %d: %d\n",++cnt, dp ); } return 0; } /* 6 5 5 2 3 5 5 */
相关文章推荐
- 居然因为交换错了好几把。。。。,还有坑点是num1可以大于num2
- 不排序的top k选择方法
- 【poj】3254corn fields
- C语言基本知识点
- iOS设计模式之观察者模式
- Android 多媒体开发学习之制作一个简单的画板
- C - Segment set
- 除法表达式-最大公约数
- 2015 Multi-University Training Contest 4
- 2015 Multi-University Training Contest 4 -- Walk Out
- AngularStrap -- Popovers
- 可自动切换选项卡
- iOS -UI汤姆猫实现(UIImageView)自己写的汤姆猫,所学知识有限,代码还有待改进 ==
- 【Linux】Shell中的正则表达式
- DOM解析XML
- Markdown
- loop_login.sh
- 全自动化的 Android 编译管线
- leetcode 071 —— Simplify Path
- 场景管理:八叉树算法C++实现