uva 529 Addition Chains

迭代深搜解决加法链问题
本文介绍了一种使用迭代深搜结合剪枝技术来解决加法链问题的方法。通过对搜索过程进行优化,实现了对特定整数n构造最短加法链的目标。

题目地址:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=470

题目描述:



  Addition Chains 

An addition chain for n is an integer sequence $<a_0, a_1, a_2, \dots, a_m>$ with the following four properties:

  • a0 = 1
  • am = n
  • a0<a1<a2<...<am-1<am
  • For each k ( $1 \le k \le m$) there exist two (not neccessarily different) integers i and j ($0 \le i, j \le k-1$) with ak =ai +aj

You are given an integer n. Your job is to construct an addition chain for n with minimal length. If there is more than one such sequence, any one is acceptable.

For example, <1,2,3,5> and <1,2,4,5> are both valid solutions when you are asked for an addition chain for 5.

Input Specification 

The input file will contain one or more test cases. Each test case consists of one line containing one integer  n  (  $1 \le n \le 10000$ ). Input is terminated by a value of zero (0) for  n .

Output Specification 

For each test case, print one line containing the required integer sequence. Separate the numbers by one blank.


Hint: The problem is a little time-critical, so use proper break conditions where necessary to reduce the search space.

Sample Input 

5
7
12
15
77
0

Sample Output 

1 2 4 5
1 2 4 6 7
1 2 4 8 12
1 2 4 5 10 15
1 2 4 8 9 17 34 68 77
题意:

a[0]=1 a[m]=n,a序列为严格递增序列, 对于任意的下标k在[1,m]内 都存在 1 <= j <= i <= k-1  使得 a[i]+a[j]=a[k],找出m最小的符合条件的序列,即长度最小的序列。

题解:

迭代深搜+剪枝

刚开始仅仅是DFS+剪枝,结果怎么剪都不行,过个300的数据就卡半天。无奈解题报告,说是迭代深搜。

迭代深搜其实就是DFS的变种(变种特别特别多,灵活变种与组合),即是一种限定了搜索深度的DFS,然后利用已限定的深度可以做各种各样的剪枝和其他操作,而整体模式更像是BFS,该深度没有答案,则深度+1,就像是一层一层的广度搜索。其实带有BFS思想的DFS以前也是写过的,也可以说算是这么一种。

对于剪枝:

1、当前深度要填的数 肯定来自于它前几位中,较大的两位组成,且其和 要小于等于末端值n 又要大于前一位的值(序列严格递增)。即  a[k-1] < a[i]+a[j]  <= n

2、对于当前要填的值 temp,由于已经确定了深搜的深度,那么 我们按最大的取值(i,j都取前一位,即a[k-1]*2) 延伸到 最大深度时候的temp,如果其值都比n小(能取的最大值都比n小),意味着在这趟搜索中它永远不可能达到n,所以剪掉这支。

代码:

/*
use IDS I have not any other way to solve it
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int a[1000]={1};//a[0]=1
int n=0;
int depth=0;
int flag=0;//find the min length
/*DFS the sequence place schedule*/
int DFS(int len,int depth)
{
	if(flag) return(0);
	if(len==depth&&a[len-1]==n)
	{
		flag=1;
		return(0);
	}
	else
	{
		int i=0,j=0;
		for(i=len-1;i>=0;i--)
		{
			for(j=i;j>=0;j--)
			{
				if(a[i]+a[j]<=n&&a[i]+a[j]>a[len-1])//prune,the sequence is strictly increasing
				{
					a[len]=a[i]+a[j];
					//prune,IDS prune
					int temp=a[len];
					int k=0;
					for(k=len+1;k<=depth;k++)
					{
						temp*=2;
					}
					if(temp<n)
					{
						continue;
					}
					DFS(len+1,depth);
					if(flag) return(0);
				}
			}
		}
	}
	return(0);
}
/*for test*/
int test()
{
	//find the law or formula
	int i=300;
	for(i=1;i<=300;i++)
	{
		printf("%d\n",i );
	}
	return(0);
}
/*main process*/
int MainProc()
{
	while(scanf("%d",&n)!=EOF&&n>0)
	{
		//init
		a[0]=1;
		depth=0;
		int temp=1;
		while(temp<n)
		{
			depth++;
			temp*=2;
		}
		depth++;//at least depth,temp>=n so depth++,it at least (not must) be this area,not the tem<n area,depth is same as len
		flag=0;
		while(!flag)
		{
			DFS(1,depth);
			if(!flag)
			{
				depth++;
			}
		}
		//out
		printf("%d",a[0] );
		int i=0;
		for(i=1;i<=depth-1;i++)
		{
			printf(" %d",a[i] );
		}
		printf("\n");
	}
	return(0);
}
int main(int argc, char const *argv[])
{
	/* code */
	//test();
	MainProc();
	return 0;
}

### 关于 Chains 的概述 Chains 是一种广泛应用于不同领域的重要概念,可以指代多种含义,包括但不限于数据结构、算法或框架。以下是关于 Chains 在各个方面的详细介绍。 #### 1. **链式约束(水平/垂直链条)** 在 Android 开发中,`Chains` 被用于描述组件之间的布局关系。通过右键菜单选择 `Create Horizontal Chain` 或 `Create Vertical Chain`,开发者能够轻松构建复杂的 UI 布局[^1]。这种技术允许组件之间形成紧密关联的链条,在调整单个组件位置时自动更新其他组件的位置。 #### 2. **路由链(RouterChain)** 在基于大语言模型的应用场景下,`RouterChain` 提供了一种动态决策机制。它利用 LLM 对输入 Prompt 进行分析,并根据推理结果选择合适的处理链[^2]。这一特性使得 RouterChain 成为复杂任务自动化流程的理想工具之一。 #### 3. **LangChain 中的链式结构(Chains)** 作为 LangChain 库的核心组成部分之一,“链”代表了一系列按顺序执行的任务步骤。下面给出一个简单示例: ```python from langchain.chains import SimpleSequentialChain from langchain.llms import OpenAI llm = OpenAI(temperature=0) # 定义两个连续操作 define_problem_chain = lambda input: llm(f"请为我生成一个与以下主题相关的问题: {input}") answer_question_chain = lambda input: llm(f"这个问题的答案是什么: {input}") # 构建链并运行 chain = SimpleSequentialChain(chains=[define_problem_chain, answer_question_chain]) result = chain.run("气候变化") print(result) ``` 上述代码片段展示了如何将多个逻辑单元串联起来形成完整的处理流水线[^3]。 #### 4. **Rust 编程环境下的 Chains 实现** 对于某些特定应用场合而言,采用 Rust 编写高性能软件可能是更优的选择。“chains”作为一个开源项目实例,遵循标准的 Rust 工程组织形式——其中 src/main.rs 文件充当入口点,而 Cargo.toml 则负责配置依赖项及相关参数设置[^4]。启动脚本如下所示: ```bash #!/bin/bash cargo run --bin chains --release ``` #### 5. **Daisy Chains 算法优化策略** 针对 Daisy Chains 类型问题,可以通过引入前缀和技巧降低时间复杂度至 O(n²)[^5]。核心思想在于预先计算数组各索引处累积值 si ,从而简化后续区间查询过程: \[ s_i = \sum_{k=1}^{i}{p_k} \] 在此基础上进一步推导得到任意子序列均值表达式: \[ average_{i,j}=\frac{s_j-s_i+p_i}{j-i+1} \] 最后遍历所有可能满足条件的情况完成统计计数工作即可实现高效解决方案。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值