枚举+剪枝,读懂题目意思后就是简单的枚举了,题目要求将一个数字分解成多个数字,并将这些数字的和与目标数字作比较。比较结果有三种情况:
1)error,所有组合的数字都比目标数字大
2)rejected,所有组合的数字中,存在多于一个不超过目标数字且最大的组合数字
3)sum=part1+part2+part3的形式,除开上述两种情况
这里还要注意一下几点:
1)注意题目中附带了一句:若输入的两数字相等。则不cut,其实这是第三种请况,但由于比较特殊,所以可以独立判别,增加速度。
2)注意在cut的过程中,有一点要明白:20022,若将其cut成这样的数字2 , 0 ,0 ,2,2,和cut成这样的数字2,0,02,2结果的和是相等的,也就是说0数字开头也要考虑中(起先没有考虑这个),这在rejected的判别中尤其要注意
3)在用深搜枚举时,减枝的关键在于将大于目标数字的情况剪掉,这样就只留下小于等于目标数字的组合数字,同时也便于判断是否是第一种情况。
下面是代码:164K+0MS
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#define Max 10
using namespace std;
int Time;
int source[Max];
int target[Max];
int ttarget[Max];
int sn,tn;
int rlen;
int slen;
int Sum;
stack<int> Sta;
bool Is_error;
int Power(int n){
int temp=1;
for(int i=1;i<=n;i++)
temp*=10;
return temp;
}
void dfs(int rindex,int num,int Count){
if(num==slen){
Is_error=false;
if(Count>Sum){
rlen=rindex;
for(int i=0;i<rlen;i++)
ttarget[i]=target[i];
Time=1;
Sum=Count;
}
else if(Count==Sum)
Time++;
return ;
}
if(Count+source[num]<=tn){
target[rindex]=source[num];
dfs(rindex+1,num+1,Count+source[num]);
}
for(int i=num+1;i<slen;i++){
int fuck=Power(i-num);
int temp=0;
for(int j=num;j<=i;j++){
temp+=fuck*source[j];
fuck/=10;
}
target[rindex]=temp;
if(Count+temp>tn)
continue;
dfs(rindex+1,i+1,Count+temp);
}
}
int main(){
while(scanf("%d%d",&tn,&sn)){
if(sn==0)
break;
if(sn==tn){
printf("%d %d\n",sn,tn);
continue;
}
int temp=sn;
while(temp>0){
Sta.push(temp%10);
temp/=10;
}
int pivot=1;
while(!Sta.empty()){
source[pivot++]=Sta.top();
Sta.pop();
}
slen=pivot;
Sum=0;
Is_error=true;
dfs(0,1,0);
if(Is_error)
printf("error\n");
else{
if(Time>1)
printf("rejected\n");
else{
printf("%d",Sum);
for(int i=0;i<rlen;i++)
printf(" %d",ttarget[i]);
printf("\n");
}
}
}
return 0;
}