【TopCoder SRM 551 Div2】Solutions

【250】

  Beaver Bindu has some colored bricks. Each color is described by an uppercase letter. Bricks of each color all look exactly the same. You are given a string bricks. Each character of bricks represents the color of one of Bindu's bricks.
  Bindu wants to arrange all her bricks into a row. A row of bricks is nice if there is at most one pair of adjacent bricks which have different colors.
  Return the number of ways in which Bindu can form a nice row, using all her bricks. (Two ways are considered identical if they correspond to the same sequence of brick colors.) 

  显然,如果只有一种颜色,就只有一中排列方案;如果有两种颜色(A、B),就只有两种方案(AB、BA);如果有大于两种颜色,就没有符合题意的方案

class ColorfulBricks{
	public:
		int countLayouts(string s){
			int cnt[100],num=0;
			memset(cnt,0,sizeof(cnt));
			for(int i=0;i<s.size();i++)
				if(cnt[s[i]-'A']) cnt[s[i]-'A']++;
				else cnt[s[i]-'A']++,num++;
			if(num>2) return 0;
			else return num;
		}
};

 

【500】

  Beaver Bindu has some chocolates arranged in a row. The wrapping of each chocolate has a single color. Multiple chocolates can share the same color. In this problem, each of the possible colors is represented by an uppercase letter. You are given a string chocolates. For each i, the i-th chocolate (0-based index) in the row has the color chocolates[i].

  The spread of a row of chocolates is the maximum number of adjacent chocolates that all share the same color. Formally, the spread can be defined as the maximum value of (j-i+1), where i <= j and all the chocolates in the positions between i and j, inclusive, have the same color.

  You are also given an int maxSwaps. Bindu can swap any two adjacent chocolates. She has decided to make at most maxSwaps such swaps. 

  Return the maximum spread she can obtain.

  因为所给的n很小(n≤50),所以幂次的方法也可以接受。

  枚举一个字母为“参照物”,它是不动的,而其他的围绕着它来交换并向它靠拢。处理完所有相同字母的距离之后,将距离排序,从小到大相加,直到最大且小于等于maxstep,更新答案。

template<class T>inline void gmax(T &a,T b){if(a<b)a=b;}
template<class T>inline void gmin(T &a,T b){if(a>b)a=b;}

class ColorfulChocolates{
	public:
		int maximumSpread(string s,int k){
			int dist[200],len=s.size(),ans=0;
			for(int i=0;i<len;i++){
				memset(dist,0x7f,sizeof(dist));
				int cnt=0;
				for(int j=i+1;j<len;j++)
					if(s[i]==s[j])
						cnt++,dist[j]=j-i-cnt;
				cnt=0;
				for(int j=i-1;j>=0;j--)
					if(s[i]==s[j])
						cnt++,dist[j]=i-j-cnt;
				sort(dist,dist+len);
				int tmp=0,x=0,t_ans=1;
				while(tmp+dist[x]<=k)
					tmp+=dist[x],t_ans++,x++;
				gmax(ans,t_ans);
			}
			return ans;
		}
};

 

【950】

  Beaver Bindu has N cupcakes. Each cupcake has one of three possible colors. In this problem we will represent the colors by uppercase letters 'A', 'B', and 'C'. Two cupcakes of the same color are indistinguishable. You are given a string cupcakes consisting of exactly N characters. Each character in cupcakes gives the color of one of Bindu's cupcakes. 

  Bindu has N friends, sitting around a round table. She wants to give each friend one of the cupcakes. Moreover, she does not want to give cupcakes of the same color to any pair of friends who sit next to each other. 

  Let X be the number of ways in which she can hand out the cupcakes to her friends. As X can be very large, compute and return the value (X modulo

1,000,000,007).

  五维DP:f[x][i][j][k][l]表示前x个数,用了i个A,j个B,k个C,第x-1位是l(l=1,2,3) 的方案数,至于首尾不相同的问题,可以枚举第一个的颜色,然后后面的DP。

class ColorfulCupcakesDivTwo{
	public:
		int countArrangements(string s){
			const int BASE=1000000007;
			int f[51][51][51][51][4],A(0),B(0),C(0),n=s.size(),ans(0);
			for(int i=0;i<n;i++)
				if(s[i]=='A') A++;
				else if(s[i]=='B') B++;
				else C++;
			for(int start=1;start<=3;start++){
				memset(f,0,sizeof(f));
				if(start==1) f[1][1][0][0][1]=1;
				else if(start==2) f[1][0][1][0][2]=1;
				else f[1][0][0][1][3]=1;
				for(int x=2;x<=n;x++)
					for(int i=0;i<=A;i++)
						for(int j=0;j<=B;j++)
							for(int k=0;k<=C;k++)
								if((i+j+k)==x){
									if(i) 	f[x][i][j][k][1]=(f[x][i][j][k][1]+f[x-1][i-1][j][k][3])%BASE,
	    									f[x][i][j][k][1]=(f[x][i][j][k][1]+f[x-1][i-1][j][k][2])%BASE; 
									if(j)	f[x][i][j][k][2]=(f[x][i][j][k][2]+f[x-1][i][j-1][k][1])%BASE,
											f[x][i][j][k][2]=(f[x][i][j][k][2]+f[x-1][i][j-1][k][3])%BASE;
									if(k)	f[x][i][j][k][3]=(f[x][i][j][k][3]+f[x-1][i][j][k-1][1])%BASE,
											f[x][i][j][k][3]=(f[x][i][j][k][3]+f[x-1][i][j][k-1][2])%BASE;
								}
				ans=ans+(f[n][A][B][C][1]+f[n][A][B][C][2]+f[n][A][B][C][3]-f[n][A][B][C][start])%BASE;
			}
			return ans%BASE;
		}
};

   但是,上面这种代码是错误的!!!!自己算算多少空间把……绝对会开爆了内存。怎么办怎么办?

   我们发现在转移时总是i+j+k==x,所以k=x-i-j,当i和j一定时,枚举k是多余的,所以可以压掉一维,正确代码如下:

 

class ColorfulCupcakesDivTwo{
	public:
		int countArrangements(string s){
			int A(0),B(0),C(0),n=s.size(),ans=0;
			const int BASE=1000000007;
			int f[51][51][51][4];
			for(int i=0;i<n;i++){
				if(s[i]=='A') A++;
				else if(s[i]=='B') B++;
				else C++;
			}
			for(int start=1;start<=3;start++){
				memset(f,0,sizeof(f));
				if(start==1) f[1][1][0][1]=1;
				else if(start==2) f[1][0][1][2]=1;
				else f[1][0][0][3]=1;
				for(int x=2;x<=n;x++)
					for(int i=0;i<=A;i++)
						for(int j=0;j<=B;j++){
									if(i)	f[x][i][j][1]=(f[x][i][j][1]+f[x-1][i-1][j][3])%BASE,
											f[x][i][j][1]=(f[x][i][j][1]+f[x-1][i-1][j][2])%BASE;
									if(j)	f[x][i][j][2]=(f[x][i][j][2]+f[x-1][i][j-1][1])%BASE,
											f[x][i][j][2]=(f[x][i][j][2]+f[x-1][i][j-1][3])%BASE;
									if(x-i-j)	f[x][i][j][3]=(f[x][i][j][3]+f[x-1][i][j][1])%BASE,
												f[x][i][j][3]=(f[x][i][j][3]+f[x-1][i][j][2])%BASE;
						}
				ans=(ans+(f[n][A][B][1]+f[n][A][B][2]+f[n][A][B][3]-f[n][A][B][start])%BASE)%BASE;
			}
			return ans;
		}
};

 

 

  人生第一次TC,最后一题因为最后时刻没有点Compile而直接submit失去了AK的机会,分数只有670分(Cha人家的很爽)。名字颜色变成黄色了,下次只能做Div1了,不知道Div1的题目有多难。反正Div2感觉是挺水的。

posted @ 2012-08-05 02:40  Delostik  阅读(507)  评论(0编辑  收藏  举报