构造数列 迭代加深dfs

[题目描述]

请构造一个尽量短的序列 A,长度为 len,一开始会给你一个正整数 n,

满足以下条件:

A[1]=1

A[len]=n

A[i]>A[i-1]                       (len>=i>=2)

A[x]=A[i]+A[j]           (1<=i,j<x)

[输入文件]

此题有多组数据,每行一个正整数n,

输入以 0 结尾

[输出文件]

每行 len 个正整数,为A 序列

[输入样例1]                                 [输出样例1]

4                                                             1 2 4

0

 [输入样例2]                           [输出样例2]

5                                                             1 2 3 5

77                                                           1 2 4 5 9 18 36 41 77

0

[数据范围]

30%:   n<=10

100%: n<=100

100%:  数据组数不超过 10 组



首先说一下什么是迭代加深dfs。

迭代加深dfs其实就是确定搜索的深度,从而避免多余的搜索,节省时间。

然后再来分析这道题。

我们看了题,知道他要我们求的是最小深度,于是我们就可以想到,最快到达目标的方法无疑是每次加深度的时候,当前的数是之前一个数的两倍。

于是,我们就得到了每个要求的目标的最小深度,那就是log(n),然后我们只需要在最小深度之上往上搜。

得到大体的思想之后,我们就需要两个剪枝来优化dfs,然后这题就可以a了。

第一个剪枝:正常剪枝,如果que[x]>n, 那就不往下搜。

第二个剪枝:如果从当前往下一直用最大的数放入数列还达不到n,那也没必要往下搜了。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
il int gi()
{
    int x=0,y=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘)
        y=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return x*y;
}
il ll gl()
{
    ll x=0,y=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘)
        y=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return x*y;
}
int n,depth;
int num[45];
bool t;
void dfs(int x)
{
//    if(depth>7)
////    return;
//    printf("x=%d t=%d depth=%d\n",x,t,depth);
//    for(int i=1;i<=depth;i++)
//    printf("%d ",num[i]);
//    printf("\n");
    if(t)
    return;
    if(x-1==depth)
    {
        if(num[x-1]==n)
        t=1;
        return;
    }
    for(int i=1;i<x;i++)
        for(int j=i;j<x;j++)
        {
            if(num[i]+num[j]>num[x-1]&&num[i]+num[j]<=n)
            {
                int now=num[i]+num[j];
//                printf("1=%d\n",now);
                for(int k=x;k<depth;k++)
                now*=2;
//                printf("2=%d\n",now);
                if(now<n)
                continue;
                num[x]=num[i]+num[j];
                dfs(x+1);
                if(t)
                return;
            }
        }
}
int main()
{while(scanf("%d",&n))
    {
        if(!n)
        return 0;
        memset(num,0,sizeof(num));
        num[1]=1;
        depth=1;
        int now=1;
        while(now<n)
        {
            depth++;
            now*=2;
        }
//        printf("depth=%d\n",depth);
        t=0;
        while(!t)
        {
            dfs(2);
            depth++;
        }
        depth--;
        printf("%d\n",depth);
        printf("%d",num[1]);
        for(int i=2;i<=depth;i++)
        printf(" %d",num[i]);
        printf("\n");
    }
}
时间: 2024-11-03 03:26:15

构造数列 迭代加深dfs的相关文章

构造数列 [迭代加深搜索]

构造数列 [题目描述] 请构造一个尽量短的序列 A,长度为 len,一开始会给你一个正整数 n,满足以下条件:A[1]=1A[len]=nA[i]>A[i-1] (len>=i>=2)A[x]=A[i]+A[j] (1<=i,j<x) [输入文件] 此题有多组数据,每行一个正整数 n,输入以 0 结尾 [输出文件] 每行 len 个正整数,为 A 序列 [输入样例 1] 4 0 [输出样例 1] 1 2 4 [输入样例 2] 5 77 0 [输出样例 2] 1 2 3 5 1

poj 3134 Power Calculus(迭代加深dfs+强剪枝)

Description Starting with x and repeatedly multiplying by x, we can compute x31 with thirty multiplications: x2 = x × x, x3 = x2 × x, x4 = x3 × x, …, x31 = x30 × x. The operation of squaring can be appreciably shorten the sequence of multiplications.

POJ-3134-Power Calculus(迭代加深DFS)

Description Starting with x and repeatedly multiplying by x, we can compute x31 with thirty multiplications: x2 = x × x, x3 = x2 × x, x4 = x3 × x, -, x31 = x30 × x. The operation of squaring can be appreciably shorten the sequence of multiplications.

[迭代加深dfs] zoj 3768 Continuous Login

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3768 Continuous Login Time Limit: 2 Seconds      Memory Limit: 131072 KB      Special Judge Pierre is recently obsessed with an online game. To encourage users to log in, this game wi

[poj 2331] Water pipe ID A*迭代加深搜索(dfs)

Water pipe Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 2265 Accepted: 602 Description The Eastowner city is perpetually haunted with water supply shortages, so in order to remedy this problem a new water-pipe has been built. Builders s

算法复习——迭代加深搜索(骑士精神bzoj1085)

题目: Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. Input 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位.两组数据

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

UVA 10160 Servicing Stations(状态压缩+迭代加深)

[题目链接] LInk [题目大意] 给出一些点和边,选择一个点就能把这个点和相邻的点都覆盖,求最小点覆盖 [题解] 我们压缩点被覆盖的状态,迭代加深搜索覆盖的最小点数, 当剩余的点全部选上时都无法完全覆盖就剪枝. [代码] #include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const int N=36; int i,n,m,x,y,limit; LL st[N],Lf

UVA-11214 Guarding the Chessboard (迭代加深搜索)

题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数. 题目分析:迭代加深搜索,否则超时. 小技巧:用vis[0][r].vis[1][c].vis[2][r+c].vis[c-r+N]分别标志(r,c)位置相对应的行.列.主.副对角线有没有被占领(详见<入门经典(第2版)>P193),其中N表示任意一个比行数和列数都大(大于等于)的数. 代码如下: # include<iostream> # include<cstdio> # include&l