P1441 砝码称重(状态压缩+bitset)

传送门

题目描述:

现有n个砝码,重量分别为 ai,在去掉 m 个砝码后,问最多能称量出多少不同的重量(不包括 0)。

请注意,砝码只能放在其中一边。

思路:dfs枚举出所有可能的选择方法,再在每种可能的方法中进行dp,

这道题由于是只有加法操作而且值比较小可以用bitset优化快速算出每个数的出现情况

#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<string.h>
#include<map>
#include<vector>
#include<bitset>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 21;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
inline int read()
{
    int f = 1, num = 0;
    char ch = getchar();
    while (0 == isdigit(ch)) { if (ch == '-')f = -1; ch = getchar(); }
    while (0 != isdigit(ch)) num = (num << 1) + (num << 3) + ch - '0', ch = getchar();
    return num * f;
}
int n, m,res;
int w[maxn];
void dfs(int pos,int now, int num) {
    if (pos > n)return;
    if (num == n - m) {
        bitset<2010>S;
        S[0] = 1;//为0的可能
        for (int i = 0; i < n; i++) {
            if (now & (1<<i)) {
                S |= S << w[i];//或就表示算上了之前的
            }
        }
        if (res < S.count()) {
            res = S.count();
        }
        return;
    }
    if(m+num>=pos+1)//剪枝
    dfs(pos + 1, now, num);
    dfs(pos + 1, now + (1 << pos), num + 1);
}
int main() {
    //freopen("test.txt", "r", stdin);
    n = read(), m = read();
    for (int i = 0; i < n; i++)w[i] = read();
    dfs(0, 0, 0);
    cout << res-1 << endl;//要减去为0的可能
    return 0;
}

 

posted @ 2021-02-24 11:10  cono奇犽哒  阅读(128)  评论(0)    收藏  举报