SCOJ 3843 ZUMA【记忆化搜索,dp】


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;
}
posted @ 2011-02-27 21:29  AndreMouche  阅读(4884)  评论(0编辑  收藏  举报