切碎公司
时限: 1000MS 内存限制: 10000K
提交总数: 7356 接受的: 3972
描述
您刚刚负责为碎纸公司开发新的碎纸机,尽管“正常”的碎纸机会将纸片切成小块,以使内容物变得不可读,但这种新的碎纸机需要具有以下与众不同的基本特征。
1.切碎机将目标编号和上面写有编号的纸张作为输入。
2.它将纸张切成薄片(或切成薄片),每个薄片上都有一个或多个数字。
3.写在每件作品上的数字总和是最接近目标数字的可能数字,无需进行遍历。
例如,假设目标数量为50,并且纸张的编号为12346。切碎机会将纸张切成四块,其中一块有1,另一块有2,第三块有34,第四块有6.这是因为它们的总和43(= 1 + 2 + 34 + 6)最接近所有可能组合的目标数字50而不会超过50。例如,一个组合是1、23、4和6无效,因为此组合34(= 1 + 23 + 4 + 6)的总和小于上述组合的43。12、34和6的组合也无效,因为总和52(= 12 + 34 + 6)大于目标数字50。
图1.当目标数量为50时切碎具有数字12346的纸
还有三个特殊规则:
1.如果目标编号与纸张上的编号相同,则不会裁切纸张。
例如,如果目标数量为100,并且纸张上的数量也为100,则
不会裁切纸张。
2.如果无法进行总和小于或等于目标数字的任何组合,则会在显示屏上显示错误。例如,如果目标数量为1,并且纸张上的数量为123,则不可能进行任何有效的组合,因为最小总和为1,2,3的组合。是大于目标数的6,因此会打印错误。
3.如果有多个可能的组合,总和最接近目标数字而不经过目标数字,则拒绝的信息会打印在显示屏上。例如,如果目标数量为15,并且纸张上的数量为111,则存在两种可能的组合,其最大和为12:(a)1和11以及(b)11和1;因此拒绝被打印。为了开发这样的粉碎机,您已经决定首先制作一个简单的程序来模拟上述特征和规则。给定两个数字,第一个是目标数字,第二个是要切碎的纸张上的数字,您需要弄清楚切碎机应如何“切出”第二个数字。
输入值
输入包含多个测试用例,每个测试用例都在一行上,如下所示:
tl num1
t2 num2
…
tn numn
0 0
每个测试用例都由以下两个正整数组成,并用一个空格分隔:(1)第一个整数(上面的ti)是目标数,(2)第二个整数(上面的numi)是要切碎的纸张上的数字。
两个整数都不能以0作为第一位数字,例如,允许123,但不允许0123。您可以假设两个整数的长度最多为6位数字。由两个零组成的线表示输入的结束。
输出量
对于输入中的每个测试用例,相应的输出采用以下三种类型之一:
和part1 part2 …
拒绝
错误
在第一种类型中,partj和sum具有以下含义:1.
每个partj是一个数字碎纸。partj的顺序与纸张上原始数字的顺序相对应。
2.sum是切碎后的数字之和,即sum = part1 + part2 + …
每个数字应以一个空格分隔。
如果无法进行任何组合,则会显示消息错误,如果存在
多个可能的组合,则拒绝该错误 。
每行的开头或每行的末尾都不允许包含空格的多余字符。
Sample Input
50 12346
376 144139
927438 927438
18 3312
9 3142
25 1299
111 33333
103 862150
6 1104
0 0
Sample Output
43 1 2 34 6
283 144 139
927438 927438
18 3 3 12
error
21 1 2 9 9
rejected
103 86 2 15 0
rejected
说说思路吧,这道题让我了解到我对dfs还是理解不够。
举例说
我们如何通过dfs穷举12346各个割位呢?看代码
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<functional>
#include<cstdio>
using namespace std;
const int maxn=1e6;
int num,a[maxn],summ,book[maxn],ans,k;
string str;
void dfs(int x,int wz,string path,int dep,int sum)
{
if(dep==0)
{
if(sum<=x&&ans<=sum)
{
str=path;
ans=max(ans,sum);
book[ans]++;
}
return;
}
for(int i=1;i<=dep;i++)//12346,割的话可分成6,46,346,2346,12346(我是倒着开始)
{
int w=wz;
int div=1;
int num=0;
string temp=path;
for(int j=0;j<i;j++)//当分为1234 6时,更新sum,与temp
{
num+=(w%10)*div;
temp+=(w%10+'0');
div*=10;
w/=10;
}
temp+=' ';
dfs(x,wz/div,temp,dep-i,sum+num);//更新wz(去掉之前的6,把1234搜索),割的位置的初始值也变为dep-i
}
}
int main()
{
while(cin>>num>>k) {
if(num==k&&k==0)
{
break;
}
str.clear();
memset(book,0,sizeof(book));
int rud=0,temp=k;
while(temp)
{
temp/=10;
rud++;
}
ans=-1;
summ=0;
dfs(num,k,str,rud,0);
if(ans==-1)
printf("error\n");
else
{
if(book[ans]==1)
{
printf("%d",ans);
for(int i=str.size()-1;i>=0;i--)
{
putchar(str[i]);
}
printf("\n");
}
else
{
printf("rejected\n");
}
}}
return 0;
}