HDU 4269 数位dp

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 15;
LL dp[maxn][2];
int a[maxn], b[maxn], c[maxn], lena, lenb, lenc, kase;
char s[50];
void init()
{
	memset(dp, 0, sizeof(dp));
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	lena = 0, lenb = 0, lenc = 0;
}
void GetABC()
{
	int pos = -1, pre;
	while (s[++pos] != '+')
		if (s[pos] == '?') a[lena++] = -1;
		else a[lena++] = s[pos] - '0';
	while (s[++pos] != '=')
		if (s[pos] == '?') b[lenb++] = -1;
		else b[lenb++] = s[pos] - '0';
	while (s[++pos] != 0)
		if (s[pos] == '?') c[lenc++] = -1;
		else c[lenc++] = s[pos] - '0';
	reverse(a, a + lena);
	reverse(b, b + lenb);
	reverse(c, c + lenc);
}
int main(int argc, char const *argv[])
{
	while (~scanf("%s", s))
	{
		init();
		GetABC();
		if (lenc < max(lena, lenb)) printf("Case %d: %d\n", ++kase, 0);
		else
		{
			for (int i = 0; i < lenc; i++)
				for (int j = (a[i] < 0 ? (lena == 1 || i < lena - 1 ? 0 : 1) : a[i]); j <= (a[i] < 0 ? 9 : a[i]); j++)
					for (int k = (b[i] < 0 ? (lenb == 1 || i < lenb - 1 ? 0 : 1) : b[i]); k <= (b[i] < 0 ? 9 : b[i]); k++)
					{
						if (c[i] < 0 || (j + k + 1) % 10 == c[i])
							dp[i][j + k + 1 >= 10 ? 1 : 0] += (i > 0 ? dp[i - 1][1] : 0);
						if ((c[i] < 0 && (i != lenc - 1)) || (c[i] < 0 && i == lenc - 1 && j + k > 0) || (lenc == 1 && c[i] < 0) || (j + k) % 10 == c[i])
							dp[i][j + k >= 10 ? 1 : 0] += (i > 0 ? dp[i - 1][0] : 1);
					}
			printf("Case %d: %lld\n", ++kase, dp[lenc - 1][0]);
		}
	}
	return 0;
}

进位的状态方程dp[i][j + k + 1 >= 10 ? 1 : 0] += (i > 0 ? dp[i - 1][1] : 0);

不进位:dp[i][j + k >= 10 ? 1 : 0] += (i > 0 ? dp[i - 1][0] : 1);

必须非常注意边界条件。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值