【ARC 123C】1, 2, 3 - Decomposition(数位DP)

1, 2, 3 - Decomposition

题目链接:ARC 123C

题目大意

给你一个数,你可以用一些每一位都是 1,2,3 其中一个的数加起来来得到它。
然后问你最少要用多少个数来加。

思路

考虑用数位 DP 来搞。

不过首先要枚举答案,再判断答案是否可行。

然后进行数位 DP,就是从低位往高位凑,那由于前导 0 0 0 是可以的,我们就会有一些数字从一些位置之后就停止填数。
那我们想我们肯定是能让他继续填更好啊。

那我们就这么设 f i , j f_{i,j} fi,j 为填到 i i i 位,进位是 j j j,最多能留着多少个数。
然后就分能全留着和不能全留着两个转移。
(不能全留也要尽可能的留,所以都会选数字 1 1 1,能留到的就是要加的大小)

然后转移就可以啦,枚举到最小的可以的答案就退出咯。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long

using namespace std;

int T, a[21], nn;
ll n;
int in[21][11];

bool check(int mid) {
	memset(in, -1, sizeof(in));
	in[0][0] = mid;
	for (int i = 0; i < nn; i++)//从低到高凑出每一位
		for (int j = 0; j <= 9; j++)//之前的进位
			if (in[i][j]) {
				for (int k = 0; k <= 9; k++) {//这一位凑出什么
					int nd = k * 10 + a[i + 1] - j;//需要加多少
					if (in[i][j] <= nd && nd <= in[i][j] * 3) in[i + 1][k] = max(in[i + 1][k], in[i][j]);//能加到这个量
						else if (nd >= 0 && nd <= in[i][j] * 3) in[i + 1][k] = max(in[i + 1][k], nd);//要多放入数
					if (nd > mid * 3) break;//超过了最大,不可能凑得到了
				}
			}
	return in[nn - 1][a[nn]] != -1 || in[nn][0] != -1;//怕它没进位(一个应该也行?)
}

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%lld", &n);
		nn = 0;
		while (n) {
			a[++nn] = n % 10;
			n /= 10;
		}	
		
		int ans = 1;
		while (1) {
			if (check(ans)) break;
			ans++;
		}
		
		printf("%d\n", ans);
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值