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