hdu 4734 数位dp
给一个数A (十进制表示形式为AnAn-1An-2 ... A2A1,定义函数 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,给一个B,求B以内的i,满足F(i)<=F(A)
Sample Input
3
0 100
1 10
5 100
Sample Output
Case #1: 1
Case #2: 2
Case #3: 13
一开始状态s设置的是前面位数的和,但是这样每次dp对应的值都不同,需要重新清空,浪费了很多时间,于是重新设置s为小于s的数目,这样dp就不用每次重新计算,而达到记忆化搜索的效果,虽然仅仅改了几行代码,但速度快了很多,状态的设置要考虑好
TLE代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 int a,b; 8 int fa; //fa的值 9 int dp[10][5000],digit[12]; 10 int cal(int n) 11 { 12 int len=1,sum=0; 13 while(n) 14 { 15 sum=sum+(n%10)*(1<<(len-1)); 16 len++; 17 n/=10; 18 } 19 return sum; 20 } 21 int dfs(int p,int s,bool e) { //位数,前面计算的和,任意填 22 if(s>fa) return 0; 23 if (p==-1) return s<=fa; 24 if (!e &&dp[p][s]!=-1) return dp[p][s]; 25 int res = 0; 26 int u = e?digit[p]:9; 27 for (int d=0;d<=u;++d) 28 { 29 int ns=s+d*(1<<p); 30 res+=dfs(p-1,ns,e&&d==u); 31 } 32 return e?res:dp[p][s]=res; 33 } 34 int solve(int n) 35 { 36 int len=0; 37 while(n) 38 { 39 digit[len++]=n%10; 40 n/=10; 41 } 42 return dfs(len-1,0,1); 43 } 44 int main() 45 { 46 int t; 47 //freopen("1.in","r",stdin); 48 scanf("%d",&t); 49 for(int i=1;i<=t;i++) 50 { 51 memset(dp,-1,sizeof(dp)); 52 scanf("%d%d",&a,&b); 53 fa=cal(a); 54 //printf("%d %d\n",a,fa); 55 printf("Case #%d: %d\n",i,solve(b)); 56 } 57 return 0; 58 }
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 int a,b; 8 int fa; //fa的值 9 int dp[12][10000],digit[12]; 10 int cal(int n) 11 { 12 int len=1,sum=0; 13 while(n) 14 { 15 sum=sum+(n%10)*(1<<(len-1)); 16 len++; 17 n/=10; 18 } 19 return sum; 20 } 21 int dfs(int p,int s,bool e) { //位数,小于s的数量,任意填 22 if (p==-1) return s>=0; 23 if(s<0) return 0; 24 if (!e &&dp[p][s]!=-1) return dp[p][s]; 25 int res = 0; 26 int u = e?digit[p]:9; 27 for (int d=0;d<=u;++d) 28 { 29 int ns=s-d*(1<<p); 30 res+=dfs(p-1,ns,e&&d==u); 31 } 32 return e?res:dp[p][s]=res; 33 } 34 int solve(int n) 35 { 36 int len=0; 37 while(n) 38 { 39 digit[len++]=n%10; 40 n/=10; 41 } 42 return dfs(len-1,fa,1); 43 } 44 int main() 45 { 46 int t; 47 //freopen("1.in","r",stdin); 48 scanf("%d",&t); 49 memset(dp,-1,sizeof(dp)); 50 for(int i=1;i<=t;i++) 51 { 52 scanf("%d%d",&a,&b); 53 fa=cal(a); 54 //printf("%d %d\n",a,fa); 55 printf("Case #%d: %d\n",i,solve(b)); 56 } 57 return 0; 58 }