P1441 砝码称重(搜索+队列dp)

题目链接:传送门

题目大意:

给你n个砝码ai,从中去掉m个后求最多的砝码可表示的重量。

n≤20,m≤4,m<n,ai≤100。

思路:

用dfs搜掉m个砝码,然后用队列dp跑出答案,维护答案。

时间复杂度是O(Cnm * na)。

#include <bits/stdc++.h>

using namespace std;

int N, M, sum;
int a[25];
bool vis[25];
bool f[2005];

int ans;

void dp()
{
    queue <int> Q;
    Q.push(0);
    for (int i = 0; i < N; i++) if (!vis[i]) {
        int len = Q.size();
        while (len--) {
            int cur = Q.front(); Q.pop();
            int nxt = cur + a[i];
            if (!f[nxt]) {
                f[nxt] = true;
                Q.push(nxt);
            }
            Q.push(cur);
        }
    }
    int cnt = 0;
    for (int i = 1; i <= sum; i++) {
        if (f[i]) {
            cnt++;
            f[i] = false;
        }
    }
    ans = max(cnt, ans);
}

void dfs(int dep, int cur)
{
    if (dep == M) {
        dp();
    }
    for (int i = cur; i < N; i++) {
        if (!vis[i]) {
            vis[i] = true;
            sum -= a[i];
            dfs(dep+1, i+1);
            sum += a[i];
            vis[i] = false;
        }
    }
}

void init()
{
    cin >> N >> M;
    sum = 0;
    ans = 0;
    memset(f, false, sizeof f);
    memset(vis, false, sizeof vis);
    for (int i = 0; i < N; i++) {
        scanf("%d", a+i);
        sum += a[i];
    }
    sort(a, a+N);
}

int main()
{
    init();
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9795204.html