poj.1416

来源:互联网 发布:网络改造 编辑:程序博客网 时间:2024/05/22 17:48

枚举+剪枝,读懂题目意思后就是简单的枚举了,题目要求将一个数字分解成多个数字,并将这些数字的和与目标数字作比较。比较结果有三种情况:

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 10using 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;}


 

 

 

0 0
原创粉丝点击