洛谷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;}



posted @ 2018-09-26 00:07  Hadesa  阅读(115)  评论(0编辑  收藏  举报