http://cs.scu.edu.cn/soj/problem.action?id=3843
SCOJ 3843 ZUMA
大意:
有100种不同的颜色,编号为1,2,3。。100.从中取n颗珠子排成一条直线,
已知将某颗珠子插入到某一位置,若与该珠子连续的相同颜色的珠子个数>=k,那么与这一连串相同颜色的珠子便可全部消去
现要消去所有珠子,问至少需要多少珠子?
分析:
记忆化搜索、、、、、语言组织能力太差,说不太清。。。。囧o(╯□╰)o
#include<stdio.h>
#include<string.h>
const int MAXN = 100+5;
const int K = 5+1;
int n,k;
int a[MAXN];
int dp[MAXN][MAXN][K];//dp[l][r][cnt];//表示解决l到r,且l左边已有cnt个连续的与l相同的颜色需要的最少步数
inline int min(int a,int b)
{
return a<b?a:b;
}
int solve(int left,int right,int cnt)//计算与left左边有连续cnt个a[left]的情况下,消去到right这段需要的最少珠子数
{
int &cur = dp[left][right][cnt];//使得cur指向当前值
if(cur!=-1)return cur;
if(left==right)
{
cur = k-cnt-1;
return cur;
}
if(left>right)
{
cur = 0;
return cur;
}
if(cnt<k-1)
cur = solve(left,right,cnt+1)+1;
else
if(cnt>=k-1)//前面已经有k-1及以上个与a[left]相同,直接消去
cur = solve(left+1,right,0);
int i;
for(i=left+1;i<=right;i++)
{
if(a[i]!=a[left])continue;
int value = solve(left+1,i-1,0)+solve(i,right,min(cnt+1,k-1));//即连接left,i
if(value<cur)cur = value;
}
return cur;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(dp,-1,sizeof(dp));
int i;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
printf("%d\n",solve(0,n-1,0));
}
return 0;
}