bzoj1939 [Croatian2010] Zuma(区间dp,状态优化技巧)

Posted live4m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1939 [Croatian2010] Zuma(区间dp,状态优化技巧)相关的知识,希望对你有一定的参考价值。

题意:

在这里插入图片描述

解法:

容易想到令d[l][r][x][t]表示:[l,r]消除到剩下t个x颜色的球,需要的最少操作次数.
状态数O(n^3),dp复杂度O(n^4),能过.

学到一个更优秀的状态设计:
令d[l][r][t]表示已经再l左边添加了t个和a[l]颜色一样的球,
此时整个区间的总操作次数.

转移方程:
对于d[l][r][t],
1.如果t<k-1,那么可以用d[l][r][t+1]+1更新.
2.如果t=k-1,那么可以和a[l]消掉,那么可以用d[l+1][r][0]更新.
3.否则枚举i,如果a[l]=a[i],那么可以将[l+1,i-1]消掉,
之后拼接部分为d[i][r][t+1],那么用d[l+1][i-1][0]+d[i][r][t+1]更新.
这里由于t>k-1与t=k-1等价,因此t可以对k-1取min,优化一下状态数.

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int d[111][111][5];
int a[111];
int n,k;
int dfs(int l,int r,int t){
    if(l>r)return 0;
    if(l==r)return k-t-1;
    if(d[l][r][t]!=-1)return d[l][r][t];
    int ans=1e9;
    if(t<k-1)ans=dfs(l,r,t+1)+1;
    else ans=dfs(l+1,r,0);
    for(int i=l+1;i<=r;i++){
        if(a[i]==a[l]){
            ans=min(ans,dfs(l+1,i-1,0)+dfs(i,r,min(k-1,t+1)));
        }
    }
    return d[l][r][t]=ans;
}
void solve(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    memset(d,-1,sizeof d);
    int ans=dfs(1,n,0);
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

以上是关于bzoj1939 [Croatian2010] Zuma(区间dp,状态优化技巧)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1939 [Croatian2010] Zuma(区间dp,状态优化技巧)

BZOJ 1180: [CROATIAN2009]OTOCI [LCT]

bzoj 1180: [CROATIAN2009]OTOCI

[bzoj1180][CROATIAN2009]OTOCI_LCT

bzoj1180: [CROATIAN2009]OTOCI

刷题BZOJ 1180 [CROATIAN2009]OTOCI