标签:理解 最大的 size 证明 手写 贪心 说明 简化 画图
这道题是一道很经典的简单dp模型(不会dp的可以先去自学简单入个门
有O(n方)或者O(nlogn)的做法,数据范围n最大不超200,显然O(n方)算法足矣
题目要求最少抽出几本书,可以转化为求最长“舒服样子”序列的元素个数w。答案即为:n-w
具体思路就是定义数组dp1[], dp2[]
dp1[i]表示从左到右看,以第i个位置为结尾,所能构成的 最长舒服序列 的 书数量
dp2[i]表示从右到左看,以第i个位置为结尾,所能构成的 最长舒服序列 的 书数量
转移方法如下:(下面是dp1[]的转移代码,dp2[]同理)
for(int i=2;i<=n;i++) //枚举i的位置
for(int j=1;j<i;j++) //枚举j的位置,显然i的上一个人必须在他左边,所以不能超过i
if(a[i]>a[j]) //必须要i的高度>j的高度才能接上去
dp1[i]=max(dp1[j]+1,dp1[i]); //如果执行到这里就说明i位置可以接到"以j位置为结尾的序列"上,那么"接"和"不接"俩选择,哪个好就选择哪个
如何算答案?只需从1-n枚举每个位置,每个位置的最优答案是dp1[i]+dp2[i]-1(减1是因为位置i统计了两次)。那么最终答案就是(n-取n个位置的最优答案中的最大值)。
感觉自己不太擅长揣测没学过dp同学的心理,所以这篇如写得不明白,还请指出。
通过观察了几组小数据我发现每次要选的数字范围为[上一个选的数+1,上一次能组成的最大面值+1]
我不会严谨地证明这个结论,但并不影响做题
得出每次选的数范围后,就可以搜索了。搜索思路即每次从范围中选一个数,然后与前面选的数合在一起算出一个最大面值。如果此时的最大面值>记录的最大面值,就将记录的最大面值更新为此时的最大面值。
这样做估计有30分(没试过),会超时。问题出在了计算最大面值这一步上,可以用背包来优化。
背包思路是定义dp[],dp[i]表示凑出i这个面值最少需要的卡片数。用完全背包模板算出dp数组,然后从1枚举到一个人为设的很大的数,如果dp[i]>n了,那么此时的最大面值就是i-1
此题完全背包代码如下:
//虽说是模板,但建议要去找资料弄懂为什么
memset(dp,0x3f,sizeof(dp)),dp[0]=0;
for(int i=1;i<=fro;i++)
for(int j=c[i];j<=c[i]*n;j++)
dp[j]=min(dp[j],dp[j-c[i]]+1);
for(int i=1;i<=c[fro]*n;i++)
if(dp[i]>n) return i-1;
标签:理解 最大的 size 证明 手写 贪心 说明 简化 画图
原文地址:https://www.cnblogs.com/BigYellowDog/p/12342625.html