码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 4734 F(x)->数位DP入门练习题

时间:2015-05-14 08:46:33      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   动态规划   

分析:数位DP的入门联系题,通过该題对数位DP有感觉了;dp[len][presum]代表长度为len权值不大于presum的数。记忆化搜索提高效率,除边界(因为边界上算出来的答案在其它数中可能是不完整的)外记录dp[len][presum]的值,下次发现以前计算过就直接return;dfs(len, presum, fg)表示求长度为len,不超过pre的全部符合条件的值。fg是控制边界的。

#include<iostream>
using namespace std;

int dp[11][20002];
int num[11];

int f(int x)         //根据题目给的公式求出f(x)
{
	int tmp,res;

	tmp=1;
	res=0;
	while(x)
	{
		res+=x%10*tmp;
		x/=10;
		tmp<<=1;
	}
	return res;
}

int dfs(int len,int presum,bool fg)  //fg为边界标志
{
	int i,end,ans;

	if(len<0) return presum>=0;//如果数组num内的数用完了,就判断f(x)中剩余的是否还有,有就说明符合要求的有一个了
	if(presum<0) return 0;      //f(x)小于当前数,不符合要求,返回0

	if(!fg && dp[len][presum]!=-1) return dp[len][presum];  //记忆化
	end=fg?num[len]:9;         //计算边界
	ans=0;

	for(i=0;i<=end;i++)
		ans+=dfs(len-1,presum-i*(1<<len),fg&&i==end);
	if(!fg) dp[len][presum]=ans;                       //边界不能进行记忆化,因为对于另外的数来说可能计算的结果是不完整的
	return ans;
}

int solve(int a,int b)
{
	int len;

	len=0;
	while(b)             //把b的每个位算出保存在num数组中
	{
		num[len++]=b%10;
		b/=10;
	}
	return dfs(len-1,f(a),true);
}

int main()
{
	int T,A,B,t;

	scanf("%d",&T);
	t=0;
	memset(dp,-1,sizeof(dp));
	while(T--)
	{
		scanf("%d%d",&A,&B);
		printf("Case #%d: %d\n",++t,solve(A,B));
	}
    return 0;
}


HDU ACM 4734 F(x)->数位DP入门练习题

标签:c   c++   acm   算法   动态规划   

原文地址:http://blog.csdn.net/a809146548/article/details/45700517

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!