• 题解 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 << "
    ";
    	return 0;
    }
    
    

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

  • 相关阅读:
    常用内建函数
    函数作用域
    异常处理语句
    迭代器---待延申扩展
    流程控制语句
    字典
    集合
    数据类型的可变与不可变
    Openstack keystone组件详解
    云计算openstack介绍(001)
  • 原文地址:https://www.cnblogs.com/yizimi/p/10056320.html
Copyright © 2020-2023  润新知