noi1805:碎纸机--搜索

本文探讨使用递归回溯算法解决特定数字组合问题的实现细节,包括状态剪枝、边界处理及避免重复计算的方法。通过实例分析,展示如何优化算法以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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






### 华为 OD 真题文档获取方式 对于准备参加华为 OD 的技术人员来说,获取高质量的真题资料是非常重要的。以下是关于如何下载或查看华为 OD 真题的相关信息。 #### 文档下载地址 可以通过以下链接访问并下载一份名为“华为OD真题.pdf”的资源文件[^1]: - **项目地址**: [https://gitcode.com/Open-source-documentation-tutorial/ee1fb](https://gitcode.com/Open-source-documentation-tutorial/ee1fb) 此仓库提供了与华为 OD 相关的题集合,适合用于备考和技术练习。 #### 题目解析语言支持 除了直接下载真题外,还可以通过一些博客文章获得针对不同编程语言的具体题解和指导。这些资源涵盖了多种主流开发语言,包括但不限于 Python、C++、Java 和 JavaScript 等[^2]: - **Python** 解析: [华为 OD 机考 Python](https://blog.youkuaiyun.com/hihell/category_12199275.html) - **C++** 解析: [华为 OD 机考 C++](https://blog.youkuaiyun.com/hihell/category_12199283.html) - **C 语言** 解析: [华为 OD 机考 True C](https://blog.youkuaiyun.com/hihell/category_12225286.html) - **Java** 解析: [华为 OD 机考 Java](https://blog.youkuaiyun.com/hihell/category_12201821.html) - **JavaScript** 解析: [华为 OD 机考 Js](https://blog.youkuaiyun.com/hihell/category_12201825.html) - **Golang** 解析: [华为 OD 机考 Golang](https://blog.youkuaiyun.com/hihell/category_12231589.html) 以上链接不仅包含了具体的题目描述,还附带了解决方案以及代码实现示例[^3]。 #### 输入验证的重要性 值得注意的是,在实际编写解决方案时应特别关注输入数据的有效性和合法性检查。例如,当处理用户数量 `n` 的情况下,需确认其是否为正整数;而对于其他参数,则要确保它们均为有效数值类型[^4]。这一步骤能够显著提升程序运行稳定性及准确性。 ```python def validate_input(n, values): """ Validate the input parameters. Args: n (int): Number of users. values (list[int]): List of system consumption values. Returns: bool: Whether all inputs are valid or not. """ if isinstance(n, int) and n > 0 and all(isinstance(x, int) for x in values): return True return False ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值