题目翻译:
公司现在要发明一种新的碎纸机,要求新的碎纸机能够把纸条上的数字切成最接近而不超过target值。比如,target的值是50,而纸条上的数字是12346,应该把数字切成四部分,分别是1、2、34、6。因为这样所得到的和43 (= 1 + 2 + 34 + 6) 是所有可能中最接近而不超过50的。(比如1, 23, 4, 和6 就不可以,因为它们的和不如43接近50,而12, 34, 6也不可以,因为它们的和超过50了。碎纸还有以下三个要求:
1、如果target的值等于纸条上的值,则不能切。
2、如果没有办法把纸条上的数字切成小于target,则输出error。如target是1而纸条上的数字是123,则无论你如何切得到的和都比1大。
3、如果有超过一种以上的切法得到最佳值,则输出rejected。如target为15,纸条上的数字是111,则有以下两种切法11、1或者1、11.
你的任务是编写程序对数字进行划分以达到最佳值。
题解:
方法有很多,
1,首先计算出纸上的数字有几位,(n);
2,分析一下题意就知道纸上数字分解后的各个数字的位数和等于n,且都是按顺序排列的;
即n=n1+n2+n3....
比如 : 12346,n=5;
n=1+1+1+1+1 : (1+2+3+4+6);
n=1+1+1+2 : (1+2+3+46);
n=1+1+3 : (1+2+346);
.....................
3,然后dfs每个情况;
这样一分析就简单多了。。
代码:(写的很丑,新手见谅)
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,sum;
int result, r;
int a[100], b[100],re[100],ks,t[100];
void dfs(int index,int s)
{
if (index >= sum)
{
if (index == sum)
{
int k = 1;
int ans = 0, kk=1;
int ts = s-1;
for (int i = 0; i < s; i++)
{
int an = 0;
for (int j = k; j <= k-1+b[i]; j++)
{
an += (a[j] * kk);
kk = kk * 10;
}
t[ts--] = an;
ans += an;
k += b[i];
kk = 1;
}
if (ans <= n)
{
if ((n-ans) <= (n-result))
{
if (ans == result)
r++;
else
r = 0;
ks = s;
result = ans;
for (int j = 0; j < s; j++)
re[j] = t[j];
}
}
}
return;
}
for (int i = 1; i <= sum; i++)
{
b[s] = i;
dfs(index + i, s+1);
}
}
int main()
{
while (cin >> n >> m)
{
int i;
if (n == m && n == 0)
break;
if (n == m)
cout << n << " " << m << endl;
else
{
result = -1;
r = 0;
for (i = 1;; i++)
{
a[i] = m % 10;
m = m / 10;
if (m == 0)
break;
}
sum = i;
dfs(0, 0);
if (result == -1)
cout << "error" << endl;
else
{
if (r != 0)
{
cout << "rejected" << endl;
}
else
{
cout << result;
for (int i = 0; i < ks; i++)
{
cout << " " << re[i];
}
cout << endl;
}
}
}
}
return 0;
}
然后上网搜了一下发现有个思路很有趣
使用矩阵表示所有可能值
假设要剪碎的是 12346
矩阵num为:
1 12 123 1234 12346
2 23 234 2346 0
3 34 346 0 0
4 46 0 0 0
6 0 0 0 0
他的内容链接:
点击打开链接