暑期dp46道(28) hdoj 1502 Regular Words dp+高精度额

来源:互联网 发布:南昌大学网络教学平台 编辑:程序博客网 时间:2024/05/16 10:18

题目链接:HDOJ 1502




题意:长为3*n的字符串有A、B、C三种字符,且对于它的任意前缀都满足num(A)>=num(B)>=num(C),且整体的   num(A)=num(B)=num(C)=n,求对于n(60>=n>=0)有多少种不同的构成串的方式。


  教训,刷这题的当天我做了好几道dfs+记忆化搜索题,恰巧这题用这个思想貌似也能做,所以顺利写下来WA,懵逼,乱改了几发交了也不行,最后求助学长,结果才发现这题的answer会爆long long,当时简直完美,不过写了一遍dfs用dp状态方程也就出来了,就是一个高精度啦,懵逼,果然还是太naive了。。


WA的dfs代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<stack>#include<queue>using namespace std;#define Max(a,b) ((a>b)?a:b)#define Min(a,b) ((a<b)?a:b)#define debug 0#define M(a) memset(a,0,sizeof(a))#define INF 1 << 28const int maxn = 60+5;int n,dp[maxn][maxn][maxn];int dfs(int x,int y,int z){if(x == n && y == n && z == n){return 1;}if(dp[x][y][z]){return dp[x][y][z];}if(x < n){dp[x][y][z] += dfs(x + 1, y, z);if(x > y){dp[x][y][z]+=dfs(x, y + 1, z);}if(y > z){dp[x][y][z]+=dfs(x, y, z + 1);}}else{if(y < n){dp[x][y][z] += dfs(x, y + 1, z);if(y > z){dp[x][y][z]+=dfs(x, y, z + 1);}}elsedp[x][y][z] += dfs(x, y, z + 1);}return dp[x][y][z];}int main(){#if debugfreopen("in.txt","r",stdin);#endif //debugwhile(~scanf("%d",&n)){M(dp);if(n == 0)printf("0\n\n");elseprintf("%d\n\n",dfs(0,0,0));}return 0;}



AC的dp高精度代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<stack>#include<queue>using namespace std;#define Max(a,b) ((a>b)?a:b)#define Min(a,b) ((a<b)?a:b)#define debug 0#define M(a) memset(a,0,sizeof(a))#define INF 1 << 28const int maxn = 60 + 5;int n;char dp[maxn][maxn][maxn][105];void sum(char a[],char b[])//高精度加法{    int lena = strlen(a);    int lenb = strlen(b);    int len = Min(lena,lenb);    int carry = 0;    int i;    for(i = 0; i < len; i ++)    {        int num = a[i] - '0' + b[i] - '0' + carry;        a[i] = num % 10 + '0';        carry = num / 10;    }    while(i < lena)    {        int num = a[i] - '0' + carry;        a[i] = num % 10 + '0';        carry = num / 10;        i++;    }    while(i < lenb)    {        int num = b[i] - '0' + carry;        a[i] = num % 10 + '0';        carry = num / 10;        i++;    }    if(carry > 0)    {        a[i] = carry + '0';        a[i + 1] = '\0';    }    else    {        a[i] = '\0';    }}void init(){    dp[0][0][0][0] = '1';    dp[0][0][0][1] = '\0';//初始值    for(int i = 1; i < 62; i++)//从dfs中很容易推出状态方程(PS:这里是字符串表示)            for(int j = 0; j <= i; j++)                    for(int k = 0; k <= j; k++)                        {                            if(i > j)                            {                                sum(dp[i][j][k], dp[i - 1][j][k]);                            }                            if(j>k)                            {                                sum(dp[i][j][k], dp[i][j - 1][k]);                            }                            if(k>0)                                sum(dp[i][j][k], dp[i][j][k - 1]);                            }}int main(){#if debug    freopen("in.txt","r",stdin);#endif //debug    init();    while(~scanf("%d",&n))    {        if(n == 0)            printf("0\n\n");        else        {            for(int i = strlen(dp[n][n][n]) - 1; i >= 0; i--)                putchar(dp[n][n][n][i]);            printf("\n\n");        }    }    return 0;}


1 0
原创粉丝点击