决策单调性&四边形不等式

#include<bits/stdc++.h>
#define MAXN 10000+10
using namespace std;
int dp[MAXN][MAXN],s[MAXN][MAXN],cnt[MAXN];
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&cnt[i]),cnt[i]=cnt[i-1]+cnt[i];
    for(int i=1;i<=n;i++)
        dp[i][i]=0,s[i][i]=i;
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            int temp=0x7fffffff;
            int te;
            for(int k=s[i][j-1];k<=s[i+1][j];k++){
                if(temp>dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1]){
                    temp=dp[i][k]+dp[k+1][j]+cnt[j]-cnt[i-1];
                    te=k;
                }
            }
            dp[i][j]=temp;
            s[i][j]=te;
        }
    }
    cout<<dp[1][n]<<endl;
}

题目:
n 堆石子。现要将石子有次序地合并成一堆,规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并得分。设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分

算法:(注:代码石子首尾不连接)
设dp(i,j)定义为第i堆石子到第j堆石子合并后的最少总分数,想到这样dp转移 
dp[i][j]=min{dp[i][k]+dp[k+1][j]}+cost[i][j] 
cost[i][j]表示把第i堆到第j堆的石子和到一起的最后一步的代价,显然之前无论怎么合并,最后一步的代价都是一样的,所以我们可以先预处理出这个cost数组,他等于cnt[j]-cnt[i-1],其中cnt数组是前缀和,然后用四边形不等式优化

合并石子问题

现在有n堆石子,要将石子按一定顺序地合成一堆,规定如下,每次只能移动相邻的两堆石子,合并费用为新和成一堆石子的数量,求把n堆石子全部合并到一起所花的最少或者最大花费

很容易想到这样一个dp转移 
dp[i][j]=min{dp[i][k]+dp[k+1][j]}+cost[i][j] 
震惊!这不就是之前所讲的模型嘛?原来之前O(n^3)方的合并石子问题还可以优化(我太弱了) 
首先明确一点,cost[i][j]表示把第i堆到第j堆的石子和到一起的最后一步的代价,显然,之前无论怎么合并,最后一步的代价都是一样的,所以我们可以先预处理出这个cost数组,他等于cnt[j]-cnt[i-1],其中cnt数组是前缀和 
for一遍i,for一遍j,每算一次dp[i][j]还要for一遍k,自然是O(n^3)方,现在我们来按照规则判断是否可以用四边形优化

第一步(壹)证明cost为凸

对于所有的i,j,令其满足i< i+1<=j< j+1 
我们需要证明 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1] 
移项 
cost[i][j]-cost[i+1][j]<=cost[i][j+1]-cost[i+1][j+1] 
令f(j)=cost[i][j]-cost[i+1][j] 
f(j)=cnt[j]-cnt[i-1]-(cnt[j]-cnt[i]) 
f(j)=cnt[i]-cnt[i-1] 
都跟j无关了,自然一定满足四边形不等式(这个时候是直接等于了,但没有违反四边形不等式)

第二步(贰)证明dp为凸

要推导dp[i][j]的凸性,自然要满足对任意的i,j,令i< i+1<=j< j+1 
有如下结论 
dp[i][j]+dp[i+1][j+1]<=dp[i+1][j]+dp[i][j+1] 
令dp[i+1][j]取得最优值的时候k=x 
令dp[i][j+1]取得最优值的时候k=y 
令x < =y(之后还要令x > y,这里不再赘述,读者如有兴趣可以自行推导,方式相似) 
将k=x代入dp[i][j],k=y代入dp[i+1][j+1] 
左式=dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1]① 
而对于i< i+1<=j< j+1 
由于已经在壹中证明了cost的凸性,所以 
cost[i][j]+cost[i+1][j+1]<=cost[i+1][j]+cost[i][j+1]② 
我们会发现这个不等式的左边在①式中出现过,所以把②式中的左式和右式替换一下可以得到如下结论 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i+1][y]+dp[y+1][j+1]+cost[i+1][j+1] 
<=

dp[i][x]+dp[x+1][j+1]+cost[i][j+1]+dp[i+1][y]+dp[y+1][j]+cost[i+1][j]

即dp[i][j]+dp[i+1][j+1]<=dp[i][j+1]+dp[i+1][j] 
证毕

第三步(叁)证明决策单调

现在我们已经证明了cost数组和dp数组的凸性,要证明决策单调以证明优化的正确性 
即要证明s[i][j-1]<=s[i][j]<=s[i+1][j] 
对于s[i][j-1]<=s[i][j] 
令dp[i][j-1]取得最小值时的k=y,对于所有x≠y,令x<=y 
可以有如下推导 
∵x+1<=y+1<=j-1< j 
四边形不等式有: 
dp[x+1][j-1]+dp[y+1][j]<=dp[y+1][j-1]+dp[x+1][j]

在式子两边同时加上dp[i][x]+cost[i][j-1]+dp[i][y]+cost[i][j] 可以得到

dp[i][x]+dp[x+1][j-1]+cost[i][j-1]+dp[i][y]+dp[y+1][j]+cost[i][j] 
<= 
dp[i][x]+dp[x+1][j]+cost[i][j]+dp[i][y]+dp[y+1][j-1]+cost[i][j-1]

dp[i][j-1]+dp[i][j]<=dp[i][j]+dp[i][j-1] 
(k=x)…………(k=y)……(k=x)……(k=y) 
移项

dp[i][j-1]-dp[i][j-1]<=dp[i][j]-dp[i][j] 
(k=x)…………(k=y)……(k=x)……(k=y)

由于我们是令k=y时dp[i][j-1]取得最小值,那么dp[i][j-1] (k=x)一定大于等于dp[i][j-1] (k=y),所以左式大于零,所以右式也大于零,所以对于dp[i][j-1]可以取到最优值的y,所有小于它的值,对于dp[i][j]来说,都没有y优,所以最优决策一定不是小于y的,如果令s[i][j]表示dp[i][j]取得最优值的时候的k值,那么一定有 
s[i][j-1]<=s[i][j] 
证毕 
 

猜你喜欢

转载自blog.csdn.net/cj1064789374/article/details/85219626