在这片梦想之地,不堪回首的过去像泡沫一样散去,不愿面对的明天也永远不会到来,|

PassName

园龄:3年1个月粉丝:32关注:16

UVA529 加成序列

传送门

题目分析

一道 dfs,迭代加深

我们可以很快的猜出来最终 m 的长度必然是小于 10 的。

而这种浅深度的问题正好适用于迭代加深。

之后考虑剪枝

优化搜索顺序 : 我们要让序列中的数字迅速地逼近 n,自然是要 ij 从大到小枚举,且 j<=i

排除等效冗余 : 我们发现,对于不同的 ij ,他们的 a[i]+a[j] 有一定的可能性会相同

所以避免重复搜索,我们需要进行判重.

好了,到这里你就可以轻松切掉《算法竞赛进阶指南》那个题了///

AcWing 170

但是在 UVA 中,n 的数据范围可是 1e5 啊!

所以还有一个剪枝,

最优化剪枝 :后面每一项最多是前一项的 2

代码实现

#include <bits/stdc++.h>

#define rint register int
#define endl '\n'

using namespace std;

const int N = 1e4 + 5;

int n, path[N];

bool dfs(int u, int k)
// u is the depth of now
// k is the depth of MAX
{
    if (path[u - 1] > n)
    {
        return false;
    }

    if (u == k)
    {
        return path[u - 1] == n;
    }

    if (path[u - 1] * ((long long)1 << (k - u)) < n)//最优化剪枝
    {
        return false;
    }

    bool st[N] = {0};//通过 bool数组排除等效冗余

    for (rint i = u - 1; i >= 0; i--)
    {
        for (rint j = i; j >= 0; j--)//搜索顺序
        {
            int s = path[i] + path[j];
            if (s > n || s <= path[u - 1] || st[s])
            {
                continue;
            }

            st[s] = true;

            path[u] = s;

            if (dfs(u + 1, k))
            {
                return true;
            }
        }
    }

    return false;
}

signed main()
{

    path[0] = 1;

    while (cin >> n and n != 0)
    {
        int depth = 1;

        while (!dfs(1, depth))// 不断扩大范围
        {
            depth++;
        }

        for (rint i = 0; i < depth - 1; i++)
        {
            cout << path[i] << " ";
        }

        cout << path[depth - 1];//UVA 输出不能有多余空格

        puts("");
    }

    return 0;
}

本文作者:PassName

本文链接:https://www.cnblogs.com/spaceswalker/p/16557117.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   PassName  阅读(43)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起