HRBUST - 1818 石子合并 区间dp入门

 有点理解了进阶指南上说的”阶段,状态和决策“

/*
区间dp的基础题:
以区间长度[2,n]为阶段,枚举该长度的区间,状态dp[l][r]表示合并区间[l,r]的最小费用
状态转移方程dp[l][r]=sum[r]-sum[l]+min(dp[l][k]+dp[k+1][r]),其中k是决策
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

int n,sum[150],a[150],dp[150][150];

int main(){
    while(scanf("%d",&n)==1){
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        memset(dp,0x3f,sizeof dp);
        for(int i=1;i<=n;i++){//初始状态 
            dp[i][i]=0;
            sum[i]=sum[i-1]+a[i];
        }
        
        for(int len=2;len<=n;len++)//阶段 
            for(int l=1;l<=n-len+1;l++){//状态;左端点 
                int r=l+len-1;//状态,右端点 
                for(int k=l;k<r;k++)//决策 
                    dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
                dp[l][r]+=sum[r]-sum[l-1];
            }
        printf("%d ",dp[1][n]); 
        
        memset(dp,0,sizeof dp); 
        for(int len=2;len<=n;len++)
            for(int l=1;l<=n-len+1;l++){
                int r=l+len-1;
                for(int k=1;k<r;k++)
                    dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);
                dp[l][r]+=sum[r]-sum[l-1];
            } 
        printf("%d\n",dp[1][n]); 
    }
}

 

posted on 2019-01-04 16:33  zsben  阅读(206)  评论(0编辑  收藏  举报

导航