OpenJudge noi1805碎纸机

Description
你现在负责设计一种新式的碎纸机。一般的碎纸机会把纸切成小片,变得难以阅读。而你设计的新式的碎纸机有以下的特点:

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,在这种情况下,打印机会显示拒绝服务信息。

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

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

sum part1 part2 … rejected error

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

如果不论怎样切割,分割得到的纸片上数的和都大于目标数,那么打印“error”。
如果有多种不同的切割方式可以得到相同的最优结果,那么打印“rejected”。
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的过程中,记录当前位,当前位前面拆分之和,并用一个now数组来存储当前位,因为条件要求拆分出的数之和必须是小于n的,所以,在这里我们可以加一个剪枝,也就是说当前面的和加上当前拆分的数>n,我们就可以return,不再继续搜索。当搜索长度大于m时,也就意味着我们已经把所有的位数拆分完了,这时候,我们将其与现在的最大值进行比较,如果它更大,我们就更新最大值,再用一个step数组记录对于当前的拆分情况,每个数是多少,每次不断进行更新。
因为题面上说如果有多种不同的切割方式可以得到相同的最优结果,那么打印“rejected”,那么我们开一个vis数组,每次当拆分完这个数的时候,对于当前的sum,vis【sum】++,最后再判断vis【ans】是否大于1就可以得出结果了

代码实现:

#include
#include
#include
#include
using namespace std;
int n,m,ans,vis[1000005],num,step[15],now[15];
char s[15];
void dfs(int dq,int sum,int cnt)
{
    if(dq>=m)
    {
        vis[sum]++;
        if(sum>ans)
        {
            ans=sum;
            num=cnt;
            for(int i=0;ireturn;                                     
    }
    int t=0;
    for(int i=dq;i10+s[i]-'0';
        if(sum+t>n)
        return;
        now[cnt]=t;
        dfs(i+1,sum+t,cnt+1);
    }
}
int main()
{
    int sum;
    while(scanf("%d%s",&n,s)!=EOF)
    {
        m=strlen(s);
        if(n==0&&s[0]=='0'&&m==1) break;
        sum=0;
        for(int i=0;i'0';
        if(sum>n)
        {
            printf("error\n");
            continue;
        }
        memset(vis,0,sizeof(vis));
        num=0,ans=0;
        dfs(0,0,0);
        if(vis[ans] > 1) 
        printf("rejected\n");  
        else
        {  
            printf("%d",ans);  
            for(int i = 0;i < num;i ++)  
                printf(" %d",step[i]);  
            printf("\n");  
        }   
    }
    return 0;
}

你可能感兴趣的:(=====复习=====,====搜索====,dfs)