碎纸机

题目OJ链接:http://bailian.openjudge.cn/practice/2803/

总时间限制: 1000ms 内存限制: 65536kB
描述
你现在负责设计一种新式的碎纸机。一般的碎纸机会把纸切成小片,变得难以阅读。而你设计的新式的碎纸机有以下的特点:

1.每次切割之前,先要给定碎纸机一个目标数,而且在每张被送入碎纸机的纸片上也需要包含一个数。
2.碎纸机切出的每个纸片上都包括一个数。
3.要求切出的每个纸片上的数的和要不大于目标数而且与目标数最接近。

举一个例子,如下图,假设目标数是50,输入纸片上的数是12346。碎纸机会把纸片切成4块,分别包含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.如果目标数和输入纸片上的数相同,那么纸片不进行切割。
2.如果不论怎样切割,分割得到的纸片上数的和都大于目标数,那么打印机显示错误信息。
3.如果有多种不同的切割方式可以得到相同的最优结果。那么打印机显示拒绝服务信息。比如,如果目标数是15,输入纸片上的数是111,那么有两种不同的方式可以得到最优解,分别是切割成1和11或者切割成11和1,在这种情况下,打印机会显示拒绝服务信息。


为了设计这样的一个碎纸机,你需要先写一个简单的程序模拟这个打印机的工作。给定两个数,第一个是目标数,第二个是输入纸片上的数,你需要给出碎纸机对纸片的分割方式。输入输入包括多组数据,每一组包括一行。每行上包括两个正整数,分别表示目标数和输入纸片上的数。已知输入保证:两个数都不会以0开头,而且两个数至多都只包含6个数字。

输入的最后一行包括两个0,这行表示输入的结束。
输出对每一组输入数据,输出相应的输出。有三种不同的输出结果:

sum part1 part2 ... 
rejected 
error 

第一种结果表示:
1.每一个partj是切割得到的纸片上的一个数。partj的顺序和输入纸片上原始数中数字出现的次序一致。
2.sum是切割得到的纸片上的数的和,也就是说:sum = part1 + part2 +...
第一种结果中相邻的两个数之间用一个空格隔开。

如果不论怎样切割,分割得到的纸片上数的和都大于目标数,那么打印“error”。
如果有多种不同的切割方式可以得到相同的最优结果,那么打印“rejected”。 
样例输入

50 12346
376 144139
927438 927438
18 3312
9 3142
25 1299
111 33333
103 862150
6 1104
0 0

样例输出

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

题目来源:翻译自Japan 2002 Kanazawa的试题

 

算法分析:

这个题,我们可以从简单到难来想。 
首先如果目标数和纸片数相同的话,直接输出他俩就完了, 
然后 如果不论怎样切割,分割得到的纸片上数的和都大于目标数,那么打印“error”。,我们一开始将答案附成一个极小值(比如说-1),如果DFS完了,答案还是极小值,说明没有答案。

如果切出来的能组成的尽量大的数有多种方案,puts(“rejected”);先立个flag,我们在DFS的过程中是不断更新答案的,如果当前搜到的答案和之前更新的答案一样,将flag=1,如果搜到了新的答案,将flag=0,这样。当flag==1的时候,puts(“rejected”);   也可这样:如果当前搜到的答案和之前更新的答案一样,则记录目前最大值出现的次数。

 

 1 #include<cstdio>  
 2 #include<cstring>  
 3 #include<vector>  
 4 using namespace std;
 5 
 6 vector<int> ans;
 7 int t,s,a[100],len;
 8 int b[100],MaxSum=0x3f3f3f3f,count;
 9 
10 bool search(int u,int sum,int n)//n表示b[]下标;sum表示目前分出来的各个数的累加和;u表示a[]下标。
11 {
12   bool flag=false;
13   
14   if(u==len)
15   {
16       if(sum<=t)
17     {
18       if(MaxSum==sum)count++;
19       else if(MaxSum<sum)
20       {
21         count=1;  
22         MaxSum=sum;  
23         ans.clear();  
24         for(int i=0;i<n;i++)ans.push_back(b[i]);  
25       }
26       return true;  
27     }
28   }
29   
30   if(sum>t) return false;
31 
32   b[n]=0;
33   for(int i=u;i<len;i++)
34   {
35     b[n]=b[n]*10+a[i];  
36     flag=search(i+1,sum+b[n],n+1)||flag;  
37   }
38   return flag;  
39 }
40 
41 int main()
42 {
43   while(scanf("%d%d",&t,&s)==2&&s&&t)
44   {
45     int temp=s;  
46     len=count=0;  
47     MaxSum=-0x3f3f3f3f;  
48     do
49     {
50       a[len++]=temp%10;  
51     }while(temp/=10);  
52     for(int i=0;i<len/2;i++)
53     {
54       temp=a[i];  
55       a[i]=a[len-i-1];  
56       a[len-i-1]=temp;  
57     }
58     
59     if(search(0,0,0))
60     {
61       if(count==1)
62       {
63         printf("%d",MaxSum);  
64         for(int i=0;i<ans.size();i++) printf(" %d",ans[i]);  
65         putchar('\n');  
66       }
67       else printf("rejected\n");  
68     }
69     else printf("error\n");  
70   }
71   return 0;  
72 }

 

 

代码来自:https://blog.csdn.net/qq_16964363/article/details/79151771

分析:https://blog.csdn.net/loi_chlorinelight/article/details/52851596

 

posted on 2018-05-05 17:38  华山青竹  阅读(475)  评论(0编辑  收藏  举报

导航