HDU3652(数位dp)

解题思路:和HDU2089相对,数位dp目前我看到两种写法。一种是初始化好dp,后面直接用,这种适用于范围比较小的时候。还有一种就是在做道题,直接带入dfs,一个询问一次dp.代码中的lim代表是不是可以0——9随便取,即限制他不能大于输入的n.总体然说感觉就是个记忆化搜索。dp[pos][sts][mo],中pos代表第pos位数,sts代表在pos-1前的状态(0表示前面没有13出现,且pos-1处的值不是1;1表示前面没有13出现,但pos-1处的值是1;2表示前面已经有完整的13出现过了),mo代表pos-1前取余后的数

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int bt[50],t;
int dp[30][3][15];
int dfs(int p,int mo,int sts,int lim)
{
	if(p==0) return (sts==2)&&(mo==0);
	if(!lim&&dp[p][sts][mo]!=-1) return dp[p][sts][mo];
	int k= lim? bt[p]:9;
	int r,m;
	int ans=0;
	for(int i=0;i<=k;i++)
	{
		r=0;
		if(sts==2)
			r=2;
		else
		if(i==1)
			r=1;
		else
		if(sts==1&&i==3)
			r=2;
		m=(mo*10+i)%13;
		ans+=dfs(p-1,m,r,lim&i==bt[p]);		
	}
	if(!lim)
	dp[p][sts][mo]=ans;
	return ans;
}
int main()
{
	//freopen("t.txt","r",stdin);
	int n;
	 while(scanf("%d",&n)!=EOF)
	 {
	 	int t=0;
	 	while(n)
	 	{
	 		bt[++t]=n%10;
	 		n/=10;
		}
		memset(dp,-1,sizeof(dp));
		printf("%d\n",dfs(t,0,0,1));
	 }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39861441/article/details/88550815