您的位置:首页 > 大数据 > 人工智能

【ZOJ 1937】 【POJ 2248】 Addition Chains

2016-04-04 17:37 381 查看


Description

对于一个数列a1,a2......am,其中a1 = 1,am = n , a1 < a2 < ... < am-1 < am 对于每个k(2<=k<=m),ak=ai+aj (1 <= i, j <= k-1),现给定n的值,要求m的最小值.


Input

整个测试有多组数据,每行一个数字N,N<=100,测试以数字零代表结束。


Output

输出有多行,每行一个数字,代表你的结果


Sample Input

5
7
12
15
77
0


Sample Output

4
5
5
6
9


HINT


Source

迭代搜索,用深度优先的话需要找出所有加法链,然后再取最小的,至少是n!的复杂度,用广度的话

找到的第一个加法链就是最短的,但是对空间占用太大

逐步深化的迭代搜索可以保证第一个找到的加法链就是最短的,又不需要太大的空间开销。

基本思想是控制回溯的搜索深度deep, 每次使deep加1,直到找到一条加法链

(更多优化):1.deep有一个下界,从此下界开始搜索,可以最大加快搜索进程

2.更多剪枝

3.最短加法链的上界,是一个幂树。

<pre name="code" class="cpp">#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
int max1(int a, int b) {
return a > b ? a : b;
}
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int flag,deep;
int n;
int a[110];
void f(int ans, int step) {
if (ans == n) {
flag=0;
return;
}
if(step==deep)return;
a[step]=ans;
for(int i=step;i>=1;i--)
{
if(a[i]*2<a[step])return;//剪枝:如果a[i]的2倍都比a[step]小,那么之后的所有结果都只会更小,所以剪掉
for(int j=i;j>=1;j--)
{
if(a[i]+a[j]<=a[step])break;
if(a[i]+a[j]>n)continue;
f(a[i]+a[j],step+1);
}
}
return;
}
// 1 2 4 8 16 32 64
int main() {
//  freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
while (scanf("%d", &n) != EOF && n) {
flag=1;
deep=0;
while(flag)
{
deep++;
f(1,1);
}
printf("%d\n", deep);
}
return 0;
}

/**************************************************************
Problem: 1252
User: xrq
Language: C++
Result: Accepted
Time:376 ms
Memory:1532 kb
****************************************************************/




POJ要求输出结果,只要在递归终止的时候输出结果就行啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: