暑期dp46道(28) hdoj 1502 Regular Words dp+高精度额
2016-08-11 14:49
381 查看
题目链接: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代码:
AC的dp高精度代码:
题意:长为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 << 28 const 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); } } else dp[x][y][z] += dfs(x, y, z + 1); } return dp[x][y][z]; } int main() { #if debug freopen("in.txt","r",stdin); #endif //debug while(~scanf("%d",&n)) { M(dp); if(n == 0) printf("0\n\n"); else printf("%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 << 28 const 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 ) - 1; i >= 0; i--) putchar(dp [i]); printf("\n\n"); } } return 0; }
相关文章推荐
- 暑期dp46道(31)--HDOJ 1087 最大上升子序列和 dp(水)
- 暑期dp46道(21)HDOJ 2059 龟兔赛跑
- 暑期dp46道(23)HDOJ 1059 Dividing 多重背包+二进制优化
- 暑期dp46道(24)HDOJ 1074 Doing Homework 状压dp
- 暑期dp46道(32)--hdoj 1171 Big Event in HDU 多重背包:
- 暑期dp46道(17)--HDOJ1114 Piggy Bank 完全背包
- 暑期dp46道(26)HDOJ 1501 Zipper dfs+记忆化搜索
- 暑期dp46道(7)--HDOJ1846 Brave Game
- 暑期dp46道(37) HDOJ 2844 COINS
- 暑期dp46道(41)--HDOJ 1978 How many ways dfs + 记忆化搜索
- 暑期dp46道(12)--HDOJ 2191 多重背包+二进制优化
- 暑期dp46道(13)——HDOJ 1160FatMouse's Speed 排序+最长严格下降子序列+回溯
- 暑期dp46道(18)--HDOJ 1024 Max Sum Plus Plus
- 暑期dp46道(33)--HDOJ 1176 免费馅饼 类树塔:
- 暑期dp46道(43)--HDOJ 1159 最长公共子序列(可不连续)
- 暑期dp46道(10)HDOJ 2602 Bone Collect 01背包
- 暑期dp46道(39)--HDOJ 2870 最大子矩阵面积...
- 暑期dp46道(5)hdoj 1421 搬寝室s
- 暑期dp46道(35)--HDOJ 2159 FATE 背包问题
- 暑期dp46道(44)--HDOJ 1058