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;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C yql){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % yql)if(p & 1)ans = 1LL * x * ans % yql;
    return ans;
}
const int N = 1005;
int n, a[N], depth;
bool vis[N];

bool dfs(int cur){
    if(cur == depth + 1){
        return a[depth] == n;
    }
    for(int i = cur - 1; i >= 1; i --){
        for(int j = i; j >= 1; j --){
            if(a[i] + a[j] > a[cur - 1] && !vis[a[i] + a[j]]){
                a[cur] = a[i] + a[j];
                vis[a[cur]] = true;
                if(dfs(cur + 1)) return true;
                vis[a[cur]] = false;
            }
        }
    }
    return false;
}

int main(){

    while(scanf("%d", &n) != EOF && n){
        for(int i = 1; ; i ++){
            memset(vis, 0, sizeof vis);
            memset(a, 0, sizeof a);
            a[1] = 1;
            depth = i;
            if(dfs(2)){
                for(int j = 1; j < depth; j ++)
                    printf("%d ", a[j]);
                printf("%d\n", a[depth]);
                break;
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/onionQAQ/p/10523953.html

时间: 2024-11-11 21:23:57

POJ 2245 Addition Chains(算竞进阶习题)的相关文章

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

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 < ... <

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

周赛 POJ 2245 Lotto

Description In the German Lotto you have to select 6 numbers from the set {1,2,...,49}. A popular strategy to play Lotto - although it doesn't increase your chance of winning - is to select a subset S containing k (k > 6) of these 49 numbers, and the

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\) ,找出符合上述四个条件的长度

POJ 3421 X-factor Chains

这条链依次乘一个因子.因为n<2^20,sqrt(n)分解因子,相同的因子相对顺序取一个. #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> #include<vector> #include<stack> #include<vector> #include<map> #

POJ 2245 Lotto dfs

给出最多13个数,从中选出6个数(升序) 给出所有方案(升序输出) DFS水题 #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N = 10; const int M = 16; int ans[N]; int a[M]; int n; void dfs(int id, int pre){ if(id == 6) { for(int i =

poj 2245 水题

求组合数,dfs即可 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 int N,m,t; 9 int a[15],vis[15]; 10 void dfs(int st,int n) 11 { 12