2017 ACM/ICPC Asia Regional Qingdao Online 1007 hdu 6212 Zuma 區間dp



Problem Description
Think about the Zuma Game. You have a row of at most 200 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 (1T100) which is the total number of test cases.
Each test case contains a line with a non-empty string of 0 and 1 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
 


題意:

給你一串01串,你可以在任意位置插入0或1,有三個及以上的連續的相同的會消去,會有連鎖反應,問至少插幾次能消完


思路:聽說是個原題,,,這場真多原題

有三種消除方式:

1.直接將區間分成兩部分,各消各的。

2.如果兩頭是同色的,可以消完中間的,合併後消去兩頭,代價和兩頭的數量有關。

3.如果兩頭同色,又存在一頭只有一個連續的情況,可以中間再找一個相同顏色的,三個合併後再消。



//
//  main.cpp
//  1007
//
//  Created by zc on 2017/9/18.
//  Copyright © 2017年 1004. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=220;
char s[N];
int a[N],f[N][N];

int main(int argc, const char * argv[]) {
    int T,kase=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int n=strlen(s),m=0;
        a[++m]=1;
        for(int i=1;i<n;i++)
        {
            if(s[i]!=s[i-1])    a[++m]=0;
            a[m]++;
        }
        for(int i=m;i>0;i--)
            for(int j=i;j<=m;j++)
            {
                if(i==j)//i==j 直接返回需要補充的數量
                {
                    f[i][j]=3-a[i];
                    continue;
                }
                f[i][j]=n+n;//初始化最大值爲2*n
                for(int k=i;k<j;k++)    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);//分成兩半考慮
                if((j-i)&1) continue;//如果間隔爲奇數,則不是同種顏色
                f[i][j]=min(f[i][j],f[i+1][j-1]+(a[i]+a[j]==2));//i和j同色,可以等中間消掉,如果兩邊都是1還得加上1的代價
                if(a[i]+a[j]<4)//如果i和j存在有1,可以i,k,j三個同色的一起消
                {
                    for(int k=i+2;k<j;k+=2)
                        if(a[k]==1) f[i][j]=min(f[i][j],f[i+1][k-1]+f[k+1][j-1]);
                }
            }
        printf("Case #%d: %d\n",++kase,f[1][m]);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章