NC200532 装货物(DFS)

题目链接

题意:
有 n 件 货 物 , 第 i 件 重 w i 吨 有 n 件货物, 第 i 件重 w_i 吨 niwi
另 有 x 个 集 装 箱 , 每 个 集 装 箱 可 以 装 重 量 不 超 过 W 吨 的 货 物 。 另有 x 个集装箱,每个集装箱可以装重量不超过 W 吨的货物。 xW
货 物 不 能 拆 分 , 问 能 否 装 下 货物不能拆分,问能否装下
题解:
n < = 20 , x , w < = 1 e 9 n<=20,x,w<=1e9 n<=20,x,w<=1e9
所 以 直 接 考 虑 暴 力 搜 索 所以直接考虑暴力搜索
用 d f s 搜 索 对 于 每 个 货 物 和 哪 个 集 合 装 在 一 起 可 以 用 一 个 集 装 箱 用dfs搜索对于每个货物和哪个集合装在一起可以用一个集装箱 dfs
所 以 直 接 对 每 个 货 物 能 放 的 盒 子 进 行 搜 索 所以直接对每个货物能放的盒子进行搜索
因 为 盒 子 数 为 m i n ( x , n ) , 不 会 比 这 个 更 多 了 因为盒子数为min(x,n),不会比这个更多了 min(x,n),
所 以 盒 子 数 最 大 为 20 , 就 可 以 进 行 暴 力 枚 举 盒 子 的 摆 放 所以盒子数最大为20,就可以进行暴力枚举盒子的摆放 20
是 一 个 3 n 算 法 , 经 过 不 能 放 时 候 的 可 行 性 剪 枝 是一个3^n算法,经过不能放时候的可行性剪枝 3n
最 终 可 以 完 成 d f s , 只 要 统 计 全 部 能 放 最终可以完成dfs,只要统计全部能放 dfs
说 明 可 以 装 下 , 否 则 不 能 说明可以装下,否则不能
AC代码

/*
    Author : zzugzx
    Lang : C++
    Blog : blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
#define mem(a, b) memset(a, b, sizeof(a))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
//const int mod = 998244353;

const double eps = 1e-6;
const double pi = acos(-1.0);
const int maxn = 1e6 + 10;
const int N = 1e2 + 5;
const ll inf = 0x3f3f3f3f;
const ll oo = 8e18;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
ll b[25], a[25];
int n, x, w;
bool dfs(int now) {
    if (now == n + 1) return 1;
    for (int i = 1; i <= min(x, now); i++) {
        if (b[i] + a[now] > w) continue;
        b[i] += a[now];
        if (dfs(now + 1)) return 1;
        b[i] -= a[now];
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
//  freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    int _;
    cin >> _;
    while (_--) {
        mem(b, 0);
        cin >> n >> x >> w;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        if (dfs(1)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值