http://noi.openjudge.cn/ch0205/1805/
题目分析:
搜索,从当前节点出发,扩展出两种状态,就是和下一个数组合与否, 超过了就剪枝,记录状态.,并判重.
先用了类似排列的做法,写了一上午,9个点过了6个,写的有的麻烦,懒得再改了.
然后参考了别人的代码,结果自己处理边界的出错,导致最后一个数是0的时候出错,然后花了不少时间才找出来.
#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
int step[8],ansstep[8],id;//step,存储分割的数组,ansstep,存储答案
int maxn,cs,re,nac,lac;//re,基数,nac等待分割的数,lac待分割数的长度 ,cs重复记录标志
char ac[8];
int num[8];//待分割的数组分成的单个数
void dfs(int sum,int cf ,int p,int depth ){//sum 记录和,cf当前数,p当前的位置,depth,组合到第几个数
if(sum+cf>re||cf>re||p>lac+1) return;
if(p==lac){//到了最后一个点,就计算.
step[depth]=cf;
int sums=sum+cf ;
if (sums<=re &&sums>=maxn){
if(sums>maxn){
memcpy(ansstep,step,sizeof(step));
maxn=sums;
cs=0;
id=depth;
}
else if(sums==maxn)cs++;
}
return;
}
step[depth]=cf;
dfs(sum+cf,num[p+1],p+1,depth+1);
if(p<=lac)dfs(sum,cf*10+num[p+1],p+1,depth);
}
int main( ){
int i;
while(1){
scanf("%d%s",&re,ac);
if(re==0 && ac[0]=='0') break;
lac=strlen(ac),nac=0;
memset(num,0,sizeof(num));
num[0]=0;
for(int i=0;i<lac;i++){
num[i+1]=ac[i]-'0';
nac=nac*10+num[i+1];
}
if(re==nac) {printf("%d %d\n",re,nac);continue;}
maxn=0;
cs=0;
id=0;
dfs(0,num[1],1,1);
if(maxn==0) printf("error\n");
else if(cs>0) printf("rejected\n");
else{
printf("%d ",maxn);
for(int i=1;i<id;i++){
printf("%d ",ansstep[i]);
}
printf("%d\n",ansstep[id]);
}
}
return 0;
}
出错的dfs
void dfs(int sum,int cf ,int p,int depth ){
if(sum+cf>re||cf>re||p>lac+1) return;
if(p==lac+1){ // 这里出错,多向下计算了一次,一般情况下没错,最后一个数字是0时候会重复计算.
if (sum<=re &&sum>=maxn){
if(sum>maxn){
memcpy(ansstep,step,sizeof(step));
maxn=sum;
cs=0;
id=depth;
}
else if(sum==maxn)cs++;
}
return;
}
step[depth]=cf;
dfs(sum+cf,num[p+1],p+1,depth+1);
dfs(sum,cf*10+num[p+1],p+1,depth);
}