noi1805:碎纸机--搜索

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);
    
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值