洛谷P1880 石子合并
NOI 1995 P1880 石子合并 【普及+/提高-】
对于任意的石子堆l和石子堆r来说,如果想要合并l,r。那么l,r之间的每堆石子都已经被合并,因此任意石子堆都可以用一个闭区间[l,r]表示这堆石子为l,r之间的石子合并而来。那么对于这个石子堆而言,肯定是中间有一个划分点K,该闭区间[l,r]就是由[l,k]和[k+1,r]组成,所以划分点k就是转移的策略/
状态转移方程如下
f1[i][j]=min(f1[i][j],f1[i][k]+f1[k+1][j]); f2[i][j]=max(f2[i][j],f2[i][k]+f2[k+1][j]);
接下来是我觉得真正本题卡的点,因为原来的数据为一个圆,如何使得这个数据变得容易进行动态规划呢,有以下两种做法:
1.朴素做法:枚举每次断开的位置,将这个圆转化为链,因为需要断开n次,所以总复杂度为O(n^4) (没有试过是否会TLE,理论上常数写小一点就不会)。
2.将这个链延长两倍,扩展成2n-1堆,对于任意的x<n,第x堆和第x+1堆相同,直接动态规划即可,时间复杂度O(8n^3),虽然空间复杂度扩大两倍,但是对于本题数据毫无影响。
博主用的是第二种方法
第二种方法存储的伪代码
scanf("%d",&n); for(int i=1;i<=n;++i){scanf("%d",&a[i]); a[i+n]=a[i];} for(int i=1;i<=n*2;++i){sum[i]=sum[i-1]+a[i]; f2[i][i]=0; f1[i][i]=0;}