Think about the Zuma Game. You have a row of at most 200200 black(0) or white(1) balls on the table at the start. Each three consecutive balls never share the same colour. You also have infinite amount of black and white balls in your hand. On each turn, you can choose a ball in your hand and insert it into the row, including the leftmost place and the rightmost place. Then, if there is a group of three of more balls in the same colour touching, remove these balls. Keep doing this until no more balls can be removed.
Find the minimal balls you have to insert to remove all the balls on the table.
Input
The first line of input contains an integer T (1≤T≤100)T (1≤T≤100) which is the total number of test cases.
Each test case contains a line with a non-empty string of 00 and 11 describing the row of balls at the start.
Output
For each test case, output the case number and the minimal balls required to insert in a line.
Sample Input
4
10101
101001001
1001001001
01001101011001100
Sample Output
Case #1: 4
Case #2: 3
Case #3: 3
Case #4: 2
题解:先保存相同的区间长度,区间合并的时候有三种情况
1.直接求,枚举区间各点
2.打掉中间的之后,两边的相遇会消掉,这个时候要满足中间的颜色差别为奇数,才能满足两边颜色相同,如果两边和大约3直接消除,否则+1
3.以中间某一个为分界线,打掉左子区间和右子区间,左中右合并,这个时候在满足2的条件下,还要满足。枚举的断点为与左右端点颜色相同,并且该点区间颜色个数为1,因为如果大约等于2的话 打掉左右一个区间后,就会和中间的消除 这个地方错了好多次 ,注意!!!
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 1e5+10;
int dp[210][210],num[210];
char s[210];
int main(){
int T;
int nn = 1;
scanf("%d", &T);
while(T--){
scanf("%s", s);
int len = strlen(s);
printf("Case #%d: ", nn++);
int cnt = 1;
num[1] = 1;
memset(dp, INF, sizeof(dp));
for(int i = 1; i < len; i++){ //相同颜色个数统计
if(s[i] == s[i-1]) num[cnt]++;
else num[++cnt] = 1;
}
for(int l = 0; l < cnt ; l++){
for(int i = 1; i <= cnt - l; i++){
int j = i + l;
if(l == 0){
dp[i][i] = 3 - num[i];
}else{
for(int k = i; k < j; k++) // 区间合并第一种
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
if(l % 2 == 0){
if(num[i] + num[j] == 2) // 第二种
dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] + 1);
else
dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
if(num[i] + num[j] <= 3) //第三种
for(int k = i + 2; k < j; k += 2)
if(num[k] == 1)
dp[i][j] = min(dp[i][j], dp[i + 1][k - 1] + dp[k + 1][j - 1]);
}
}
}
}
printf("%d\n", dp[1][cnt]);
}
return 0;
}