【dp】CF17C. Balance

http://codeforces.com/problemset/problem/17/C

    题目中给出一个仅含有a,b,c的字符串,已经两种操作每次选出任意两个相邻的字符,用第一个覆盖掉第二个或者反之,最后询问不考虑操作次数,最终有多少种不同的序列其中a,b,c三种字符两两间相差不超过1个。

      很有趣的动态规划,一开始一直在考虑边构造目标串边dp,考虑前i个含有多少a,b,c之类都找不到可以在时限内通过的办法,后来重新审题发现可以重定义其两种操作,可以这样等价的描述原串通过这两种操作可以到达的目标串,将目标串相邻的重复元素去掉,剩下的元素所组成的序列,一定是原串的子序列!重定义之后很容易想到一种新的状态表示方式,dp[i][a][b][c],当前目标串含有3个字符分别a,b,c个,同时匹配到原串的第i位,的方案数,转移只要简单枚举一下下一个字符就行。详见代码

View Code
 1 //By Lin
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define MOD 51123987 
 6 using namespace std; 
 7 
 8 int        n;
 9 int        dp[155][52][52][52];
10 int        nxt[155][3];
11 char    str[155];
12 
13 int        next(int i,int k){
14     for (; i<n; i++) if ( str[i]-'a' == k ) return i;
15     return -1;
16 }
17 inline    void add(int &x,int y ){
18     x += y;
19     if ( x>=MOD ) x-=MOD;
20 }
21 int        main(){
22     scanf("%d%s", &n, str );
23     for (int i = 0; i<n; i++) 
24         for(int k = 0; k<3; k++ ) 
25             nxt[i][k] = next(i,k);
26     int lim = (n+2)/3;
27     dp[0][0][0][0] = 1;
28     int ans = 0; 
29     for (int i = 0; i<n; i++)
30         for (int a1 = 0; a1<=lim; a1++)
31             for (int a2 = 0; a2<=lim; a2++)
32                 for (int a3 = 0; a3<=lim; a3++){
33                     if ( dp[i][a1][a2][a3] == 0 ) continue;
34                     if ( a1+a2+a3 == n ) {
35                         if ( abs(a1-a2)<=1 && abs(a1-a3)<=1 && abs(a2-a3)<=1 ){
36                             add(ans,dp[i][a1][a2][a3]);
37                         }
38                         break;
39                     }
40                     if ( nxt[i][0] != -1 )
41                         add(dp[nxt[i][0]][a1+1][a2][a3] , dp[i][a1][a2][a3]);
42                     if ( nxt[i][1] != -1 )
43                         add(dp[nxt[i][1]][a1][a2+1][a3] , dp[i][a1][a2][a3]);
44                     if ( nxt[i][2] != -1 )
45                         add(dp[nxt[i][2]][a1][a2][a3+1] , dp[i][a1][a2][a3]);
46                 }
47     printf("%d\n", ans );
48     return 0;
49 }

 

posted @ 2012-12-07 15:40  lzqxh  阅读(222)  评论(0编辑  收藏  举报