山东省赛的一道题

题意:

聚会一个圆桌,相邻字母不能重复,有ABC三种字母

问有多少种方法

思路:

dp

第一维滚动,第二维ABC当前位置,后三维存ABC用的个数

由于放在了UPCOJ上,判题比较慢,优化了一下,

在SDUTIJ上20ms

/* ***********************************************
Author        :devil
Created Time  :2016/5/14 17:19:27
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
const int mod=1e9+7;
int dp[2][3][27][27][27],a[3];
int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    char s[51];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        int l=strlen(s);
        a[0]=1,a[1]=1,a[2]=1;
        for(int i=0; i<l; i++)
            a[s[i]-'A']++;
        if(a[0]>a[1]) swap(a[0],a[1]);
        if(a[1]>a[2]) swap(a[1],a[2]);
        if(a[0]+a[1]<=a[2])
        {
            printf("0\n");
            continue;
        }
        l+=3;
        long long ans=0;
        for(int y=0; y<3; y++)
        {
            memset(dp,0,sizeof(dp));
            if(y==0) dp[0][0][2][1][1]=1;
            else if(y==1) dp[0][1][1][2][1]=1;
            else dp[0][2][1][1][2]=1;
            int cur=0;
            for(int cnt=5; cnt<=l; cnt++)
            {
                cur^=1;
                for(int i=1; i<=min(a[0],cnt); i++)
                {
                    for(int j=1; j<=min(a[1],cnt); j++)
                    {
                        int k=cnt-i-j;
                        if(k>a[2]) continue;
                        dp[cur][0][i][j][k]=dp[cur^1][1][i-1][j][k]+dp[cur^1][2][i-1][j][k];
                        if(dp[cur][0][i][j][k]>=mod) dp[cur][0][i][j][k]-=mod;
                        dp[cur][1][i][j][k]=dp[cur^1][0][i][j-1][k]+dp[cur^1][2][i][j-1][k];
                        if(dp[cur][1][i][j][k]>=mod) dp[cur][1][i][j][k]-=mod;
                        dp[cur][2][i][j][k]=dp[cur^1][1][i][j][k-1]+dp[cur^1][0][i][j][k-1];
                        if(dp[cur][2][i][j][k]>=mod) dp[cur][2][i][j][k]-=mod;
                    }
                }
            }
            if(y==0) ans+=dp[cur][1][a[0]][a[1]][a[2]]+dp[cur][2][a[0]][a[1]][a[2]];
            else if(y==1) ans+=dp[cur][0][a[0]][a[1]][a[2]]+dp[cur][2][a[0]][a[1]][a[2]];
            else ans+=dp[cur][0][a[0]][a[1]][a[2]]+dp[cur][1][a[0]][a[1]][a[2]];
            while(ans>=mod) ans-=mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}