原题网址
由于某些原因,这个网址会进不去…
题目描述
m x y mxy mxy给普及组小朋友们找了点事情做。给定一个数字字符串,用最少次数的加法让字符串等于一个给定的目标数字。每次加法就是在字符串的某个位置插入一个加号。在需要的所有加号都插入后,就象做普通加法那样来求值。例如,考虑字符串" 12 12 12",做 0 0 0次加法,我们得到数字 12 12 12。如果插入 1 1 1个加号,我们得到 3 3 3。因此,这个例子中,最少用 1 1 1次加法就得到数字 3 3 3。再举一例,考虑字符串" 303 303 303“和目标数字 6 6 6,最佳方法不是” 3 + 0 + 3 3+0+3 3+0+3",而是" 3 + 03 3+03 3+03"。能这样做是因为 1 1 1个数的前导 0 0 0不会改变它的大小。写一个程序来实现这个算法。
格式
输入格式
1 1 1行: 1 1 1个字符串 S ( 1 ≤ S S(1\le S S(1≤S的长度 ≤ 40 ) \le40) ≤40)和 1 1 1个整数 N ( 0 ≤ N ≤ 1000 ) N(0\le N\le1000) N(0≤N≤1000)。 S S S和 N N N之间用 1 1 1个空格分隔。
输出格式
一行
1
1
1个整数
K
K
K,表示最少的加法次数让
S
S
S等于
N
N
N。
如果怎么做都不能让
S
S
S等于
N
N
N,则输出“
−
1
-1
−1”。
样例
输入样例
2222 8
输出样例
3
解题思路
这道题需要用到 d f s dfs dfs(深度优先搜索)。每次搜索,我们需要知道当前深度(字符串的哪个位置)、当前加号的个数、当前总和以及当前加数四个参数。因此可以分别设置形参:int dep, int add, int sum, int num。虽然有前导零,但我们有多种方式解决。这里演示了其中一种方法。
Code
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#define maxn 100 // 作者标准设置
using namespace std;
int n, ans = maxn;
string s;
void init() // 在此执行预处理
{
cin>>s>>n;
}
void dfs(int dep, int add, int sum, int num) // dep表示搜索深度(字符串的哪个位置),add表示加号个数,sum表示和,num表示当前加数
{
if (sum > n || num > n || add >= ans) return;
if (dep == s.size())
{
if (sum + num == n) ans = add; // 由于前面已经return,这里不需要比较
return;
}
dfs(dep + 1, add, sum, num * 10 + s[dep] - '0'); // 不在当前位置放加号
dfs(dep + 1, add + 1, sum + num, s[dep] - '0'); // 在当前位置放加号
}
void oput() // 在此输出总结果
{
if (ans == maxn) cout<<-1; // 如果ans等于maxn,说明没有一种方案可行,即输出-1
else cout<<ans; // 否则输出最优解
}
int main()
{
init();
dfs(0, 0, 0, 0);
oput();
return 0;
}
大功告成 ∼ \sim ∼