POJ2248 Addition Chains

Addition Chains

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5273   Accepted: 2833   Special Judge

Description

An addition chain for n is an integer sequence with the following four properties:

  • a0 = 1
  • am = n
  • a0 < a1 < a2 < ... < am-1 < am
  • For each k (1<=k<=m) there exist two (not necessarily different) integers i and j (0<=i, j<=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

The
input will contain one or more test cases. Each test case consists of
one line containing one integer n (1<=n<=100). Input is terminated
by a value of zero (0) for n.

Output

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

Source

Ulm Local 1997

【题解】

搜索层数较少,使用ID-DFS

剪枝1:ID升序枚举

剪枝2:数列降序枚举

剪枝3:保证数列递增

剪枝4:step > ID跳出

然而无论怎么剪枝,都比不上打表

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #define min(a, b) ((a) < (b) ? (a) : (b))
 6 #define max(a, b) ((a) > (b) ? (a) : (b))
 7
 8 inline void read(int &x)
 9 {
10     x = 0;char ch = getchar(), c = ch;
11     while(ch < ‘0‘|| ch > ‘9‘)c = ch, ch = getchar();
12     while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘, ch = getchar();
13     if(c == ‘-‘)x = -x;
14 }
15
16 const int MAXN = 100 + 10;
17
18 int num[MAXN], n, b[MAXN], ID;
19
20 int dfs(int step)
21 {
22     if(num[step - 1] == n) return 1;
23     if(step > ID)return 0;
24     register int tmp;
25     for(register int i = step - 1;i >= 1;-- i)
26         for(register int j = i;j >= 1;-- j)
27         {
28             tmp = num[i] + num[j];
29             if(tmp <= num[step - 1] || b[tmp] || tmp > n)continue;
30             num[step] = tmp;
31             b[tmp] = 1;
32             if(dfs(step + 1)) return 1;
33             b[tmp] = 0;
34         }
35     return 0;
36 }
37
38 int main()
39 {
40     num[1] = 1;
41     while(scanf("%d", &n) != EOF && n)
42     {
43         for(register int i = 1;i <= n;++ i)
44         {
45             ID = i;
46             memset(b, 0, sizeof(b));
47             if(dfs(2))
48             {
49                 for(register int j = 1;j <= i;++ j)
50                     printf("%d ", num[j]);
51                 putchar(‘\n‘);
52                 break;
53             }
54         }
55     }
56     return 0;
57 } 

POJ 2248

时间: 2024-09-30 18:33:29

POJ2248 Addition Chains的相关文章

poj2248 Addition Chains 迭代加深搜索

Addition Chains Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5454   Accepted: 2923   Special Judge Description An addition chain for n is an integer sequence <a0, a1,a2,...,am="">with the following four properties: a0 = 1 a

POJ2248 Addition Chains 迭代加深

不知蓝书的标程在说什么,,,,于是自己想了一下...发现自己的代码短的一批... 限制搜索深度+枚举时从大往小枚举,以更接近n+bool判重,避免重复搜索 #include<cstdio> #include<iostream> #include<cstring> #define R register int using namespace std; inline int g() { R ret=0; register char ch; while(!isdigit(ch

POJ 2248 Addition Chains dfs(水)

题意:给出n 构成出满足下列条件 长度最小的数列a[0]=1,a[m]=n, a[0]<a[1]<..<a[m]每个下标k都存在(i,j<k) 满足:a[k]=a[i]+a[j] n<=100 枚举长度 dfs爆搜+剪枝 水过, #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N=2e5+20; int n,a[N

ZOJ1937:Addition Chains——题解

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1937 题目大意:创造一个数列,使得它: 1.单调不递减. 2.其中一个元素一定存在其前面两个元素之和与它相等. 3.开头为1,结尾为n. 求一个这样的最短数列. —————————————————————————————————— IDA*一定的(n<=100) 对于IDA*是什么不了解的,可以看我的置顶骑士精神那道题. 我们的估价函数就是当前的值翻多少次二倍后能得到n.

UVA529 Addition Chains

题意: 一个与 nn 有关的整数加成序列 $<a_0,a_1,a_2,...,a_m>$ 满足以下四个条件:1.$a_0=1$ 2.$a_m=n$3.$a_0<a_1<a_2<...<a_{m-1}<a_m$4. 对于每一个 k(1≤k≤m) 都存在有两个整数 i 和 j(0≤i,j≤k-1,i和 j 可以相等 ) ,使得 $a_k=a_i+a_j$?你的任务是:给定一个整数 nn ,找出符合上述四个条件的长度最小的整数加成序列. 如果有多个满足要求的答案,只需要

POJ 2245 Addition Chains(算竞进阶习题)

迭代加深dfs 每次控制序列的长度,依次加深搜索 有几个剪枝: 优化搜索顺序,从大往下枚举i, j这样能够让序列中的数尽快逼近n 对于不同i,j和可能是相等的,在枚举的时候用过的数肯定不会再被填上所以可以去重(记得回溯) #include <iostream> #include <cstring> #include <cstdio> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; inl

C++解题报告 : 迭代加深搜索之 ZOJ 1937 Addition Chains

此题不难,主要思路便是IDDFS(迭代加深搜索),关键在于优化. 一个IDDFS的简单介绍,没有了解的同学可以看看: https://www.cnblogs.com/MisakaMKT/articles/10767945.html 我们可以这么想,设当前规定长度为M,题目要求得出的数为N. 在搜索中,当前的步数为step,当前的数列为 数组a. 首先来确定思路,便是在以得出的数列a中枚举每两个数相加得出sum,然后继续搜索下一步. 初步的代码便是: void iddfs(int x) { for

Addition Chains

POJ n<=100 洛咕 n<=10000 题意:满足如下条件的序列a被称为"加成序列": \(1.a_1=1\) \(2.a_m=n\) \(3.a_1<a_2<...<a_{m-1}<a_m\) \(4.\)对于每一个\(k(1≤k≤m)\)都存在有两个整数 \(i\) 和 \(j(1≤i,j≤k-1,i\) 和 \(j\) 可以相等 ) ,使得 \(a_k=a_i+a_j\) 你的任务是:给定一个整数 \(n\) ,找出符合上述四个条件的长度

UVA题目分类

题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494 - Kindergarten Counting Game 414 - Machined Surfaces 490 - Rotating Sentences 445 - Marvelous Mazes