@xiaoziyao
        
        2020-05-30T15:48:25.000000Z
        字数 1606
        阅读 1743
    解题报告
[COCI 2010] ZUMA解题报告:
题意:给定个珠子,每个珠子有一个颜色,每次操作可以在某一个位置插入任意一种颜色的珠子,当存在大于等于个连续的珠子为相同颜色时,这些珠子便会消失,求让所有珠子消失的最小操作数。
为了方便,在这里我们用表示。
首先我们很容易看出来这是一个区间。
一开始我们想设为消除从到的珠子的最小操作数,然而这行不通,因为无法转移(而且数据范围也提醒你肯定不会这么简单)。
我们设一个三维数组代表在前面有个与第一颗珠子相同的珠子时,消除区间与前面的个珠子的最小操作数。
首先给初始化最大值,然后设置初始值(即区间长度为的情况):f[i][i][j]=t-j-1;
然后,开始考虑如何转移(枚举区间长度,然后枚举区间起点,即可以得到终点,最后枚举,即为在区间前的珠子数量):
最后记得分类讨论一下,如果的话最好单独拎出来: 
1. 第一个转移方式改为。 
2. 第二个转移方式改为(这个地方有点难懂,其实就是因为只要有连续大于等于个相同颜色的珠子就可以消掉,因此多一颗珠子是没有关系的)。 
3. 第三个转移方式的第二个消除方式改为(原因同上)。
代码:
#include<stdio.h>#include<string.h>const int maxn=105,maxt=10;int i,j,k,m,n,p,t,len;int a[maxn],f[maxn][maxn][maxt];inline int min(int a,int b){return a<b? a:b;}int main(){memset(f,0x3f,sizeof(f));scanf("%d%d",&n,&t);for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=1;i<=n;i++)for(j=0;j<t;j++)f[i][i][j]=t-j-1;for(len=2;len<=n;len++)for(i=1;i+len-1<=n;i++){int j=i+len-1;f[i][j][t-1]=min(f[i][j][t-1],f[i+1][j][0]);if(a[i]==a[i+1])f[i][j][t-1]=min(f[i][j][t-1],f[i+1][j][t-1]);for(p=i+2;p<=j;p++)if(a[i]==a[p])f[i][j][t-1]=min(f[i][j][t-1],f[i+1][p-1][0]+f[p][j][t-1]);for(k=t-2;k>=0;k--){f[i][j][k]=min(f[i][j][k],f[i][j][k+1]+1);if(a[i]==a[i+1])f[i][j][k]=min(f[i][j][k],f[i+1][j][k+1]);for(p=i+2;p<=j;p++)if(a[i]==a[p])f[i][j][k]=min(f[i][j][k],f[i+1][p-1][0]+f[p][j][k+1]);}}printf("%d\n",f[1][n][0]);return 0;}
