题意:给一个n,求出一个长度为3n,由A,B,C组合而成的字符串的种类数。
组合条件:
1。字符串中个数:A= B = C
2。字符串的任意前缀,数量A >= B >= C。
我们可以用动态规划来做,dp[i][j][k]表示,此字符串中A的数量为i,B的数量为j, C的数量为k。那么dp[i][j][k] = dp[i - 1][j][k] + dp[i][j - 1][k] + dp[i][j][k - 1]。
其中应该满足的条件是i >= j >= k。
由于数据太大,需要高进度处理,量太大而范围小,需要打表。
#include<cstdio>
#include<cstring>
const int maxn = 60 + 5;
const int maxt = 100;
char dp[maxn][maxn][maxn][maxt];
int main()
{
//memset(dp, 0, sizeof(dp));
dp[0][0][0][1] = 1;
for(int i = 1; i < maxn; i++)
for(int j = 0; j <= i; j++)
for(int k = 0; k <= j; k++)
{
for(int t = 1; t < maxt - 2; t++)
{
dp[i][j][k][t] += dp[i - 1][j][k][t];
if(j >= 1) dp[i][j][k][t] += dp[i][j - 1][k][t];
if(k >= 1) dp[i][j][k][t] += dp[i][j][k - 1][t];
dp[i][j][k][t + 1] += dp[i][j][k][t] / 10;
dp[i][j][k][t] = dp[i][j][k][t] % 10;
}
if(i == j && j == k)
{
int temp = maxt;
while(!dp[i][j][k][temp]) temp--;
dp[i][j][k][0] = temp;
//printf("%d %d %d %d\n\n", i, j, k, temp);
}
}
int m;
while(scanf("%d", &m) == 1)
{
int p = dp[m][m][m][0];
//printf("%d\n", p);
for(int i = p; i >= 1; i--) printf("%c", dp[m][m][m][i] + '0');
printf("\n\n");
}
return 0;
}