[DP]BZOJ 1939 [Croatian2010] Zuma 题解
题目描述
祖玛游戏是这样的:有一列 n n n个有颜色的珠子,如果触碰连续 K K K个同色的珠子,那么它们就会消失,其余的珠子按照原来顺序接在一起。
现在你每次可以发射任意颜色的珠子,发射在任意位置(开头、结尾以及任意两个之间)。
注意,如果有连续 k k k个或更多同色的珠子,你可以不立即消去他们,详见样例 3。
问最少需要几发可以消掉所有的珠子。
对于所有数据, 1 ≤ N ≤ 100 , 2 ≤ K ≤ 5 , 1 ≤ a i ≤ 100 1≤N≤100,2≤K≤5,1≤ai≤100 1≤N≤100,2≤K≤5,1≤ai≤100
输入格式
第一行 N , K N,K N,K
第二行 n n n 个数 a i ai ai,不同的数表示不同的颜色
输出格式
一个答案
样例数据
input1
2 5
1 1
output1
3
input2
5 3
2 2 3 2 2
output2
2
input3
10 4
3 3 3 3 2 3 1 1 1 3
output3
4
解题分析
COCI的题果然很巧(gui)妙(yi)。这道题数据不大,DP上。祖玛怎么玩?可以在球的前面不断放同色系的球来消除,所以我们的DP也可以这么考虑, f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示从i到j全部消掉,其中要在i前面加k个i同色球最少需要多少球,所以有两种操作:
1.在i前面加1个i同色球,然后判断能否消完:
f [ i ] [ j ] [ k ] = ( k + 1 < K ) ? f [ i ] [ j ] [ k + 1 ] + 1 : f [ i + 1 ] [ j ] [ 0 ] f[i][j][k]=(k+1<K)?f[i][j][k+1]+1:f[i+1][j][0] f[i][j][k]=(k+1<K)?f[i][j][k+1]+1:f[i+1][j][0]
2.枚举与i同色的x,把 [ i + 1 , x − 1 ] [i+1,x-1] [i+1,x−1]消光,然后把i加到 [ x , j ] [x,j] [x,j]内
f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , f [ x − 1 ] ) f[i][j][k]=min(f[i][j][k],f[x-1]) f[i][j][k]=min(f[i][j][k],f[x−1])
用记忆化DFS方便转移。
示例代码
BZOJ是权限题,所以可以去洛谷(我没测过)测或COCI官网下载数据2009~2010 Test 5。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,a[105],f[105][105][10];
int _dfs(int L,int R,int x){
if (f[L][R][x]!=-1) return f[L][R][x];
if (L>R) return 0; if (L==R) return k-x-1;
int ans=(x<k-1)?_dfs(L,R,x+1)+1:_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,x+1)));
return f[L][R][x]=ans;
}
int main()
{
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",&a[i]);
memset(f,255,sizeof(f)); printf("%d",_dfs(1,n,0)); return 0;
}