[题解]和
来源:互联网 发布:怎么发淘宝链接给别人 编辑:程序博客网 时间:2024/04/30 11:06
[题目描述]
给定一个长度为n的序列,你每次可以合并相邻两个元素,新的元素为这两个元素的和。你需要使得若干
次合并之后的序列非降,求最小合并次数。
[数据范围]
n<=1500
[题解]
这道题的标程用的是n^2log(n)的dp,所以才会有奇葩的1500的范围.
然而,这道题完全可以在O(n^2)的时间内解决.
考虑前i个数的决策.如果我们要合并成合法序列后,最后的值最小,那么我们一定要使合并的次数最小.因为在如果合并次数最少且最后的值最小的情况下再进行合并,最后的值显然不会变大,即:不可能出现一种情况,使得合并的次数不是最少而最后面的值最小.因为我们一切的合并操作都是"被逼"的,所以多合并不可能使最后的数变大,于是上面的结论也可以很容易的想出来.
Code:
program sequence;type int=longint;var i,j,k,m,n:int; a,f,g,s:array[0..1500]of int;begin assign(input,'sequence.in');reset(input); assign(output,'sequence.out');rewrite(output); read(n); for i:=1 to n do begin read(a[i]);s[i]:=s[i-1]+a[i];end; fillchar(f,sizeof(f),100); fillchar(g,sizeof(g),100); f[1]:=0;g[1]:=a[1]; for i:=2 to n do begin for j:=1 to i-1 do begin if(f[j]+i-j-1<=f[i])and(g[j]<=s[i]-s[j])then begin g[i]:=s[i]-s[j];f[i]:=i-j-1+f[j]; end; end; end; write(f[n]); close(input);close(output);end.
考试时因为前两题太水了,本以为第三题会搞一道难题防AK的,所以就随便打了个贪心,只搞到了10分.知道正解这么简单后简直想吐血= =.
有很多人觉得这样dp的正确性不好证,其实这样做的正确性是显然的,到时候我再将完整版题解搞上来.
//=================================================================================================
好了,考也考完了.现在我来讲一下这道题目的线性做法.
将方程变形得到:
F[i]=min(f[j]-j)+i-1,G[j]+s[j]<=s[i].
显然,F[j]-j随j单调不增,s[i]单调上升.
于是,我们维护这样一个单调队列,使得下标单调递增(即F[j]-j单调递减),G[j]+s[j]单调上升,之后怎么做应该都会了吧.
BY QW
转载请注明出处
- [题解]和
- Codevs2155连续和题解
- 1.17题解和总结
- Sicily1005. 最大和题解
- sequencefile 和arraywritable问题解
- 【题解】[nyoj509]因子和阶乘
- 加密和安全-题解<1>
- 校赛反思和题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 【C/C++学习】之十四、RTTI
- js call
- sigsuspend详解
- js中apply方法的使用
- Geomagic点云的拼接(Registration)与合并(Merge使用Geomagic12)
- [题解]和
- sigsuspend用法
- 文件读写小练习
- 可重入和不可重入函数
- centos svn安装及配置与使用
- .net中windows form参数传递过程
- WM_CTLCOLOR消息
- Arbitrage poj2240
- Oracle 联机重做日志文件(ONLINE LOG FILE)