[DP]BZOJ 1939 [Croatian2010] Zuma 题解

[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 1N100,2K5,1ai100

输入格式

第一行 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 &lt; K ) ? f [ i ] [ j ] [ k + 1 ] + 1 : f [ i + 1 ] [ j ] [ 0 ] f[i][j][k]=(k+1&lt;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,x1]消光,然后把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[x1])

用记忆化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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值