算法实践10 装载问题

问题:

\(n\)个集装箱上两艘在中分别为\(c_1\)\(c_2\)的轮船,\(w_i\)为集装箱\(i\)的重量,且\(\sum_{i=1}^nw_i \leq c_1 + c_2\)

问是否存在一种合理的装载方案将\(n\)个集装箱装上轮船?如果有,给出一种方案。

解析

要找到可能的情况,那么我们枚举每个点放在1号船还是2号船的情况,放的过程中看看能否符合题目要求。

设计

bool dfs(int u) {
    if (u > n) return true;
    for (int i = 1; i <= 2; ++i) {
        if (c[i] + box[u].w > m[i]) continue;
        c[i] += box[u].w;
        path[i][++path[i][0]] = box[u].id;
        if (dfs(u + 1)) return true;
        path[i][0]--;
        c[i] -= box[u].w;
    }
    return false;
}

分析

最坏情况下每个点都要进行两种情况的尝试,时间复杂度\(O(2^n)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验10 装载问题

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"

const int inf = 0x3f3f3f3f;
const int N = 1e3 + 7;

int c[3], m[3], w[N], path[3][N], vis[N];
int n;

struct Box {
    int id, w;

    bool operator < (const Box & a) const {
        return w > a.w;
    }
}box[N];

bool dfs(int u) {
    if (u > n) return true;
    for (int i = 1; i <= 2; ++i) {
        if (c[i] + box[u].w > m[i]) continue;
        c[i] += box[u].w;
        path[i][++path[i][0]] = box[u].id;
        if (dfs(u + 1)) return true;
        path[i][0]--;
        c[i] -= box[u].w;
    }
    return false;
}

void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &w[i]);
        box[i] = {i, w[i]};
    }
    scanf("%d %d", &m[1], &m[2]);
    sort(box + 1, box + 1 + n); // 优先遍历重量大的箱子,加快回溯
    if (!dfs(1)) {
        puts("ERROR");
        return;
    }
    for (int i = 1; i <= 2; ++i) {
        printf("%d号轮船装了%d个箱子,总重量为%d,分别是", i, path[i][0], c[i]);
        for (int j = 1; j <= path[i][0]; ++j) {
            printf(" %d号", path[i][j]);
        }
        printf("箱子\n");
    }
}

int main() {
    // scanf("%d", &t);
    int t = 1;
    while (t--) solve();
    return 0;
}
/*
7
90 80 40 30 20 12 10
152 130
*/
posted @ 2021-06-23 08:59  stff577  阅读(117)  评论(0)    收藏  举报