hdu 4249

一題挺噁心的dp,寫了我140行,講講思路吧。

狀態:dp[len][i][j][k],表示三個數的第len位分別爲i,j,k。

限制條件:不能有前導0

轉移方程 

if((i+j)%10==k)

dp[len][i][j][k]+=dp[len-1][ii][jj][kk];其中ii+jj==kk||ii+jj+1==kk

if((i+j+1)%10==k)

dp[len][i][j][k]+=dp[len-1][ii][jj][kk];

其中ii+jj>=10&&(ii+jj)%10==kk,ii+jj+1>=0,(ii+jj+1)%10==kk

最後答案是sum(dp[len-1][i][j][k]), (i+j==k||i+j+1==k)

Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
6275054 2012-07-20 12:11:02 Accepted 4249 93MS 324K 2870 B C++ Sadly_Snoopy
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#define LL __int64
using namespace std;
int len1,len2,len3,a[15],b[15],c[15];
LL dp[10][10][10][10];
stack<char> st;
LL DP()
{
	memset(dp,0,sizeof(dp));
		for(int i=0;i<10;i++)
		{
			if(a[0]!=-1&&a[0]!=i)
				continue;
			for(int j=0;j<10;j++)
			{
				if(b[0]!=-1&&b[0]!=j)
					continue;
				for(int k=0;k<10;k++)
				{
					if(c[0]!=-1&&c[0]!=k)
						continue;
					if((i+j)%10==k)
						dp[0][i][j][k]=1;
				}
			}
		}
	for(int l=1;l<len3;l++)
	{
		for(int i=0;i<10;i++)
		{
			if(a[l]!=-1&&a[l]!=i)
				continue;
			if(l==len1-1&&i==0)
				continue;
			if(l>=len1&&i!=0)
				continue;
			for(int j=0;j<10;j++)
			{
				if(b[l]!=-1&&b[l]!=j)
					continue;
				if(l==len2-1&&j==0)
					continue;
				if(l>=len2&&j!=0)
					continue;
				for(int k=0;k<10;k++)
				{
					if(c[l]!=-1&&c[l]!=k)
						continue;
					if(l==len3-1&&k==0)
						continue;
					if((i+j)%10!=k&&(i+j+1)%10!=k)
						continue;
					if((i+j)%10==k)
					{
						for(int ii=0;ii<10;ii++)
							for(int jj=0;jj<10;jj++)
								for(int kk=0;kk<10;kk++)
								{
									if(dp[l-1][ii][jj][kk]!=0&&(ii+jj==kk||ii+jj+1==kk))
										dp[l][i][j][k]+=dp[l-1][ii][jj][kk];
								}
					}
					if((i+j+1)%10==k)
					{
						for(int ii=0;ii<10;ii++)
							for(int jj=0;jj<10;jj++)
								for(int kk=0;kk<10;kk++)
								{
									if(dp[l-1][ii][jj][kk]!=0&&(((ii+jj)>=10&&(ii+jj)%10==kk)||((ii+jj+1)>=10&&(ii+jj+1)%10==kk)))
										dp[l][i][j][k]+=dp[l-1][ii][jj][kk];
								}
					}
				}
			}
		}
	}
	LL ans=0;
	for(int i=0;i<10;i++)
		for(int j=0;j<10;j++)
			for(int k=0;k<10;k++)
			{
				if(dp[len3-1][i][j][k]!=0&&(i+j==k||i+j+1==k))
				 ans+=dp[len3-1][i][j][k];
			}
	return ans;
}
int main()
{
	char s[105];
	int t=1;
	while(~scanf("%s",s))
	{
		int i=0,len=strlen(s),flag=0;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		for(;s[i]!='+';i++)
			st.push(s[i]);
		len1=0;
		while(!st.empty())
		{
			if(st.top()!='?')
			a[len1++]=st.top()-'0';
			else a[len1++]=-1;
			st.pop();
		}
		for(i++;s[i]!='=';i++)
			st.push(s[i]);
		len2=0;
		while(!st.empty())
		{
			if(st.top()!='?')
			b[len2++]=st.top()-'0';
			else b[len2++]=-1;
			st.pop();
		}
		for(i++;i<len;i++)
			st.push(s[i]);
		len3=0;
		while(!st.empty())
		{
			if(st.top()!='?')
			c[len3++]=st.top()-'0';
			else c[len3++]=-1;
			st.pop();
		}
		if(len3>=max(len2,len1))
		printf("Case %d: %I64d\n",t++,DP());
		else printf("Case %d: 0\n",t++);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章