其他分享
首页 > 其他分享> > POJ3252 Round Numbers(数位DP)

POJ3252 Round Numbers(数位DP)

作者:互联网

在二进制数上进行数位DP,在dp数组中就记录num0和num1,方便递归到边界时判断该数是否为round number,是则加1。

套用记忆化递归模板:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int dp[40][40][40];
 5 int dig[12];
 6 /*求一个区间内Round Numbers(二进制0的个数不小于1的个数)的个数。 
 7   状态dp[pos][num0][num1];
 8   pos为当前数位,num0为二进制中0的个数,num1为二进制中1的个数; 
 9   lead表示前导零; 
10   limit表示数位限制。
11 */
12 
13 int dfs(int pos,int num0,int num1,bool lead,bool limit){//前导0,限制 
14     if(pos==0) return num0>=num1;
15     if(!limit&&!lead&&dp[pos][num0][num1]!=-1) return dp[pos][num0][num1];
16     int len=limit?dig[pos]:1;
17     int ans=0;
18     for(int i=0;i<=len;i++){
19         if(lead&&!i) ans+=dfs(pos-1,0,0,1,limit&&i==len);
20         else ans+=dfs(pos-1,num0+(i==0),num1+(i==1),0,limit&&i==len);
21     }
22     if(!limit&&!lead) dp[pos][num0][num1]=ans;
23     return ans;
24 }
25 
26 int solve(int x){
27     int pos=0;
28     while(x){
29         dig[++pos]=x%2;//转化为二进制处理每一位 
30         x/=2;
31     }
32     return dfs(pos,0,0,1,1);
33 }
34 
35 int main(){
36     int a,b;
37     memset(dp,-1,sizeof(dp));
38     while(~scanf("%d%d",&a,&b)){
39         memset(dp,-1,sizeof(dp));
40         printf("%d\n",solve(b)-solve(a-1));
41     }
42     return 0;
43 }

 

标签:num0,num1,int,pos,limit,dp,POJ3252,Round,DP
来源: https://www.cnblogs.com/yhxnoerror/p/16410054.html