Zuma
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 349 Accepted Submission(s): 95
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.
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) 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.
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
Source
【题意】给你一个01序列,你可以在任意位置加0或者1,没三个及其以上连续的0或者1在一起立马删去,问删完最少需要加入多少01.
【分析】典型区间dp,我们先离散,记录每个连续0,1出现的个数,dp[l][r]表示消去区间[l,r]最少需要多少01,那么dp[l][r]我们可以通过 如下几种状态转移。
如果l与r所在的数字相同,那么我们可以将中间部分删除完后再将他俩删除,比如11......11,此时我们可以将中间的省略号消去后,三 个1就碰到了一起,再消去;
或者,从中间找到某个与两端数字相同的点,例如11......1......1,我们可以先将右边的省略号消去,就成了11......11,然后再将中间的 省略号消去,四个1 一起消去。
但是这种转移要注意的是,这个游戏是有先后顺序的,如果你找的中间点k,他的个数是2的话,例如11......11......1,你无论先消去哪 个省略号,中间的11总会提前消去,
就不能等5个一起消去了,而且两边不能同时为两个,同样的道理,这是遵守游戏规则。
然后对于一般情况,都可以将区间分为两部分来消除,详情见代码。
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define met(a,b) memset(a,b,sizeof a) #define pb push_back #define mp make_pair #define rep(i,l,r) for(int i=(l);i<=(r);++i) #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 2e2+50;; const int M = 255; const int mod = 19260817; const int mo=123; const double pi= acos(-1.0); typedef pair<int,int>pii; int n,cas; char str[N]; int dp[N][N]; int a[N],cnt[N]; int main(){ int T; scanf("%d",&T); while(T--){ scanf("%s",str);printf("Case #%d: ",++cas); n=0; met(dp,inf); int c=0,pre=str[0]-'0'; for(int i=0;i<strlen(str);i++,c++){ if(str[i]-'0'!=pre){ cnt[++n]=c; a[n]=pre; c=0;pre=str[i]-'0'; } } cnt[++n]=c; a[n]=pre; for(int i=1;i<=n;i++)dp[i][i]=(cnt[i]==1?2:1); for(int len=2;len<=n;len++){ for(int l=1;l+len-1<=n;l++){ int r=l+len-1; if(a[l]==a[r]){ dp[l][r]=min(dp[l][r],dp[l+1][r-1]+(cnt[l]+cnt[r]>=3?0:1)); if(cnt[l]+cnt[r]<=3){ for(int k=l+2;k<=r-2;k+=2){ if(cnt[k]==1)dp[l][r]=min(dp[l][r],dp[l+1][k-1]+dp[k+1][r-1]); } } } for(int k=l;k<r;k++)dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]); } } printf("%d\n",dp[1][n]); } return 0; }