Codeforces 1312 E. Array Shrinking (区间dp)

题意:

相同的两个x可以合并成x+1,给一个序列,问最后最少能剩下多少个元素。n (1≤n≤500) 

题解

看了别人的题解后自己的理解。

dp[i][j]表示i到j区间合并后的最小个数,合并左右两个区间前提是两个区间dp值为1并且元素相等。

简单的证明:分割点为w,左区间最优合并后剩下 2、5 ,右区间最优合并后剩下5,

在w之前,i到w'合并后为2,w’到end两个五合并后为6,这时已经和分割点为w合并的情况一样了。

a[i][j]为合并后剩的元素,初始化为-1,只有区间i,j剩的元素个数为1时,a[i][j]!=-1.

状态转移方程
if(dp[j][w]==1&&dp[w+1][end]==1&&a[j][w]==a[w+1][end])
dp[j][end]=1,a[j][end]=a[j][w]+1;

dp[j][end]=min(dp[j][w]+dp[w+1][end],dp[j][end]);

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define check system("pause")
#define all(x) (x).begin(),(x).end()
#define de(a) cout<<#a<<" = "<<a<<endl
#define dd(a) cout<<#a<<" = "<<a<<" "
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define lowbit(a) ((a)&-(a))
#define INF 0x3f3f3f3f
const ll mod = 1e9+7;
const int N = 1e6+20;
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define mes(p,b) memset(p,b,sizeof(p))
#define sz(x) int(x.size())
int a[501][501],dp[501][501];
int main()
{
      ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    mes(a,-1);
    mes(dp,0x3f);
    rep(i,1,n){
        cin>>a[i][i];
        dp[i][i]=1;
    }
    rep(len,2,n)    
        for(int j=1;j+len-1<=n;j++){
            int end=j+len-1;
            rep(w,j,end-1){
                dp[j][end]=min(dp[j][w]+dp[w+1][end],dp[j][end]);
                if(dp[j][w]==1&&dp[w+1][end]==1&&a[j][w]==a[w+1][end])
                dp[j][end]=1,a[j][end]=a[j][w]+1;
            } 
        }
    cout<<dp[1][n];
      return 0;
}

 

posted @ 2020-03-11 17:37  FZU_LH  阅读(202)  评论(0编辑  收藏  举报