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; }