算法实践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
*/

浙公网安备 33010602011771号