P1874 快速求和

image

快速求和

题目描述

给定一个数字字符串,用最小次数的加法让字符串等于一个给定的目标数字。每次加法就是在字符串的某个位置插入一个加号。在里面要的所有加号都插入后,就像做普通加法那样来求值。

例如,考虑字符串12,做 \(0\) 次加法,我们得到数字 \(12\)。如果插入 \(1\) 个加号,我们得到 \(3\),因此,这个例子中,最少用 \(1\) 次加法就得到数字 \(3\)

再举一例,考虑字符串303和目标数字 \(6\),最佳方法不是3+0+3。而是3+03。能这样做是因为一个数的前导 \(0\) 不会改变它的大小。

输入格式

第一行:一个字符串 \(s\)

第二行:一个整数 \(n\)

输出格式

一行一个整数表示最少的加法次数让 \(s\) 等于 \(n\)。如果怎么做都不能让 \(s\) 等于 \(n\) ,则输出 \(-1\)

样例 #1

样例输入 #1

99999
45

样例输出 #1

4

提示

数据规模与约定

对于 \(100\%\) 的数据,保证 \(1\le \operatorname{len}(s)\le40\)\(1 \leq n\le10^5\)

解析

这道题的解析好像也没啥可说的,就是爆搜+剪枝就可以过了,读入时将字符转化为数值方便处理,搜索时有两种情况,在该位置加上加号和不加加号,不断向下搜。

代码

#include <bits/stdc++.h>
using namespace std;
string s;
int a[50], res = 0x3f3f3f3f, len, n;
void dfs(int step, int ans, int sum, int now) {
//step表示当前处理的位数,ans是加号数
//sum是最后一个加号前的总和,now表示还在累加的值(加号还未确定) 
	if (ans > res || sum > n || now > n) return ;//剪枝 
	if (step > len) {
		if (sum + now == n) res = ans;//更新答案 
		return ;
	}
	now = 10 * now + a[step];
	dfs(step + 1, ans + 1, sum + now, 0);//添一个加号 
	dfs(step + 1, ans, sum, now);//不添加号 
}
int main() {
	cin >> s >> n; 
	len = s.length();//字符串长度 
	for (int i = 1; i <= len; i ++) a[i] = s[i - 1] - '0';//取出每一位,转成数值 
	dfs(1, 0, 0, 0);//从第一位开始搜索 
	if (res >= len) cout << -1 << '\n';
	else cout << res << '\n';
	return 0;
}

image

posted @ 2022-10-13 20:18  YHXo  阅读(259)  评论(0)    收藏  举报