acwing算法提高之搜索--迭代加深DFS、双向DFS、IDA*

123 篇文章 1 订阅
本文介绍了如何使用迭代加深DFS、双向DFS和IDA*算法解决C++编程中的四个问题:加成序列、送礼物、排书和回转游戏。每个问题都展示了如何通过递归和搜索策略找到最优解或满足特定条件的解。
摘要由CSDN通过智能技术生成

1 专题介绍

本专题用来记录使用迭代加深DFS、双向DFS和IDA*算法求解的问题。

2 训练

题目1170加成序列

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110;

int n;
int path[N];

bool dfs(int u, int k) {
    if (u == k) return path[u - 1] == n;
    
    bool st[N] = {0};
    for (int i = u - 1; i >= 0; --i) {
        for (int 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;
}

int main() {
    path[0] = 1;
    while (cin >> n, n) {
        int k = 1;
        while (!dfs(1, k)) k++;
        
        for (int i = 0; i < k; ++i) cout << path[i] << ' ';
        cout << endl;
    }
    
    return 0;
}

题目2171送礼物

C++代码如下,

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long LL;

const int N = 1 << 24;

int n, m, k;
int g[50], weights[N];
int cnt = 0;
int ans;

void dfs(int u, int s) {
    if (u == k) {
        weights[cnt++] = s;
        return;
    }
    
    if ((LL)s + g[u] <= m) dfs(u + 1, s + g[u]);
    dfs(u + 1, s);
}

void dfs2(int u, int s) {
    if (u == n) {
        int l = 0, r = cnt - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (weights[mid] + (LL)s <= m) l = mid;
            else r = mid - 1;
        }
        if (weights[l] + (LL)s <= m) ans = max(ans, weights[l] + s);
        return;
    }
    
    if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]);
    dfs2(u + 1, s);
}

int main() {
    cin >> m >> n;
    for (int i = 0; i < n; ++i) cin >> g[i];
    
    sort(g, g + n);
    reverse(g, g + n);
    
    k = n / 2; //防止n=1时,出现死循环
    dfs(0, 0);
    
    sort(weights, weights + cnt);
    int t = 1;
    for (int i = 1; i < cnt; ++i) {
        if (weights[i] != weights[i - 1]) {
            weights[t++] = weights[i];
        }
    }
    cnt = t;
    
    dfs2(k, 0);
    
    cout << ans << endl;
    return 0;
}

题目3180排书

C++代码如下,

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 15;

int n;
int q[N];
int w[5][N];

int f() {
    int cnt = 0;
    for (int i = 0; i + 1 < n; ++i) {
        if (q[i + 1] != q[i] + 1) {
            cnt++;
        }
    }
    return (cnt + 2) / 3;
}

bool check() {
    for (int i = 0; i + 1 < n; ++i) {
        if (q[i + 1] != q[i] + 1) {
            return false;
        }
    }
    return true;
}

bool dfs(int depth, int max_depth) {
    if (depth + f() > max_depth) return false;
    if (check()) return true;
    
    for (int len = 1; len <= n; ++len) {
        for (int l = 0; l + len - 1 < n; ++l) {
            int r = l + len - 1;
            for (int k = r + 1; k < n; ++k) {
                memcpy(w[depth], q, sizeof q);
                int x, y;
                for (x = r + 1, y = l; x <= k; ++x, ++y) q[y] = w[depth][x];
                for (x = l; x <= r; ++x, ++y) q[y] = w[depth][x];
                if (dfs(depth + 1, max_depth)) return true;
                memcpy(q, w[depth], sizeof q);
            }
        }
    }
    return false;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 0; i < n; ++i) cin >> q[i];
        
        int depth = 0;
        while (depth < 5 && !dfs(0, depth)) depth++;
        if (depth >= 5) puts("5 or more");
        else cout << depth << endl;
    }
    
    return 0;
}

题目4181回转游戏

C++代码如下,

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 24;

int q[N];
int op[8][7] = {
    {0, 2, 6, 11, 15, 20, 22},
    {1, 3, 8, 12, 17, 21, 23},
    {10, 9, 8, 7, 6, 5, 4},
    {19, 18, 17, 16, 15, 14, 13},
    {23, 21, 17, 12, 8, 3, 1},
    {22, 20, 15, 11, 6, 2, 0},
    {13, 14, 15, 16, 17, 18, 19},
    {4, 5, 6, 7, 8, 9, 10}
};
int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};
int opposite[8] = {5, 4, 7, 6, 1, 0, 3, 2};

int path[100];

int f() {
    static int sum[4];
    memset(sum, 0, sizeof sum);
    for (int i = 0; i < 8; ++i) sum[q[center[i]]]++;
    
    int s = 0;
    for (int i = 1; i <= 3; ++i) s = max(s, sum[i]);
    return 8 - s;
}

bool check() {
    for (int i = 1; i < 8; ++i) {
        if (q[center[i]] != q[center[0]]) {
            return false;
        }
    }
    return true;
}

void operation(int x) {
    int t = q[op[x][0]];
    for (int i = 0; i < 6; ++i) q[op[x][i]] = q[op[x][i + 1]];
    q[op[x][6]] = t;
}

bool dfs(int depth, int max_depth, int last) {
    if (depth + f() > max_depth) return false;
    if (check()) return true;
    
    for (int i = 0; i < 8; ++i) {
        if (opposite[i] == last) continue;
        operation(i);
        path[depth] = i;
        if (dfs(depth + 1, max_depth, i)) return true;
        operation(opposite[i]);
    }
    return false;
}

int main() {
    while (scanf("%d", &q[0]), q[0]) {
        for (int i = 1; i < N; ++i) scanf("%d", &q[i]);
        int depth = 0;
        while (!dfs(0, depth, -1)) {
            depth++;
        }
        if (!depth) printf("No moves needed");
        for (int i = 0; i < depth; ++i) printf("%c", 'A' + path[i]);
        printf("\n%d\n", q[6]);
    }
    
    return 0;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YMWM_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值