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;

}

你可能感兴趣的:(dp)