1. 程式人生 > >題解 P1441 【砝碼稱重】

題解 P1441 【砝碼稱重】

題目描述

現有n個砝碼,重量分別為a1,a2,a3,……,an,在去掉m個砝碼後,問最多能稱量出多少不同的重量(不包括0)。

【資料規模】

對於20%的資料,m=0;

對於50%的資料,m≤1;

對於50%的資料,n≤10;

對於100%的資料,n≤20,m≤4,m<n,ai≤100。

主要思路 : 爆搜 + XJB剪枝 + XJB判重

對,就是爆搜。我們暴力搜尋一下我們要哪幾個砝碼要選。這裡就涉及一個XJB剪枝:我們記錄一下這是我們有幾個砝碼不選,如果超過m的話就不能繼續不選了。

我們枚舉出了哪幾個砝碼要選後如何搞有多少重量可以稱出來呢??

我們可以先把我們選的幾個砝碼的重量放在一個vector裡好了,我們每次到一個要選砝碼中,把vector中的每個重量加上當前選的砝碼的重量,如果這個重量沒有被出現過,就加入vector,然後把這個重量的判重bool陣列相應位置標上。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 22
#define mk 2010
#define inf 1 << 30
#define ll long long
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n, m, a[mn], maxx = -1, ans = 0;
bool f[mk], b[mn];
vector<int> get;
inline void get_ans(int x) { 
    // 打完才想到可以直接迴圈QAQ,做題時寫遞迴寫傻了
    if(x == n + 1) 
        return;
    if(b[x]) {
        int kkk = get.size();
        if(!f[a[x]]) get.push_back(a[x]);
        f[a[x]] = true;
        go(i, 0, kkk - 1, 1) {
            int zcy = get[i] + a[x];
            if(!f[zcy]) get.push_back(zcy);
            f[zcy] = true;
        }
    }
    get_ans(x + 1);
}
inline void dfs(int x, int now) {
    if(x == n + 1) {
        if(now != m) 
            return;
        // 初始化啊QwQ!
        ans = 0;
        memset(f, false, sizeof f);
        while(!get.empty()) get.pop_back();
        get_ans(1);
        // 統計答案(上限為Σa[i],我很懶,直
        // 接maxn * max(a[i]))
        go(i, 1, 2000, 1) 
            if(f[i]) ans++;
        maxx = max(maxx, ans);
        return;
    }
    if(now > m) 
        return;
    b[x] = true;
    dfs(x + 1, now);
    b[x] = false; // 有個不選的就要把計數 + 1
    dfs(x + 1, now + 1);
}
int main() {
    n = read(), m = read();
    go(i, 1, n, 1) a[i] = read();
    dfs(1, 0);
    cout << maxx << "\n";
    return 0;
}

P.S.:考前祝全國OIer NOIP 2018 RP++!!!