您的位置:首页 > 其它

hdu 4734 F(x) 数位DP

2015-08-10 20:58 337 查看
一,题意:

该题定义了一个函数 : F(x)=An * 2n-1 +
An-1 * 2n-2 + ... + A2 *
2 + A1 * 1。


现在他给定两个数,A,B,要求你求出在区间[0,B] 有多少个x ,使得F(x)<=F(A)。

二,解析:

该题主要应用了,数位dp的思想+记录状态dp的思想。

1,数位dp思想主要数是用数组来存储数,通过对数组每一位进行枚举(0,1,2,,,9),

到达便利区间[0,N]内所有数的目的

例如: 比456小的数,可以这么考虑:





这样就可以遍历[0,456]区间所有的数。



2,记录状态思想,记录下程序已走过的路,当在次走相同的路时直接返回。

至于这么判断是否走同一条路是一般是通过函数参数值,如果用同样的参数去调用同一个函数则所走的路必然是相同的。

所以dp[i][j],数组下标i,j一般表示的就是调用函数的参数。

三:代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int T,N,M;
int bit[15];
int Max[15];
int dp[15][200000];
//dp[len][sum]表示长度为len且权值不大于sum的数的个数。
int DFS(int len,int sum,bool Big)
{//len所搜索到的长度,sum是F
剩余的部分,big标记前驱是不是最大数
if(sum<0)
return 0;
if(len<=0)
return 1;//两个边界
if(!Big&&dp[len][sum]!=-1)
return dp[len][sum];//记录状态
int bian=9;
if(Big)//第len位的边界
bian=Max[len];
int key=0;
for(int i=0;i<=bian;i++)
key+=DFS(len-1,sum-(i*bit[len]),Big&&(i==bian));
if(!Big)
dp[len][sum]=key;
return key;
}
int solve(int n,int m)
{
int key=0;
int len=1;
while(n)
{//计算F

key=key+(n%10)*bit[len];
len++;
n=n/10;
}
len=0;
while(m)
{//分解M
Max[++len]=m%10;
m=m/10;
}
return DFS(len,key,true);
}

int main()
{
bit[1]=1;
for(int i=2;i<=11;i++)
bit[i]=bit[i-1]*2;
memset(dp,-1,sizeof(dp));
scanf("%d",&T);
for(int k=1;k<=T;k++)
{
scanf("%d%d",&N,&M);
printf("Case #%d: %d\n",k,solve(N,M));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: