Java教程

涛涛的天平(二进制枚举)

本文主要是介绍涛涛的天平(二进制枚举),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目描述
涛涛有N个砝码和一个没有游标的天平,砝码可以放左边,也可以放右边,问可不可以测出所问的重量, 问的个数为Q个.
输入
第一行T,表示T组数据。 (1≤T≤5)
接下来
第一行一个数N,表示砝码个数。(1≤N≤20)
第二行N个数,表示砝码们的重量wi (1≤w​i≤100)。
第三行一个数Q,表示询问个数。(1≤Q≤100)
之后Q行每行一个数k,表示一个询问的重量。
输出
对于每组数据,输出"YES"或者"NO"(不带引号)
输入样例
1
2
1 4
3
2
4
5

输出样例
NO
YES
YES

提示
对于第1个询问:无法称重
对于第2个询问:可称重 将4个砝码单独放置
对于第3个询问:可称重 将4个砝码和1个砝码放在两侧

解题思路:因为砝码是可以放在天平的里两边,因此我们不仅需要求出不同砝码组合在一起放在一边所能达到的重量,也需要求出不同重量减去还未选用的砝码的质量所能达到的质量,就是不仅要做二进制枚举的和,还要做二进制枚举的差,因此我们就需要在每次枚举求和之久就将那个质量进行枚举做减法,从而在更小的时间复杂度上完成运算,不多说了,直接上代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main (){
	int n,t,q,Q;
	int vis[2010];//根据桶排序原理,用下标表示所能称出的重量,能称出对应下标的重量就将其标为1,注意数组要稍微大一点
	int A[30]; //存储不同的砝码质量

	cin >> t;
	while (t--) {

		cin >> n;
		memset(vis,0,sizeof(vis));//初始化标记数组,使其为0,需要导入cstring包	

		for (int i = 0;i < n;i++)
			cin >> A[i];
		for(int i = 0;i < (1 << n);i++) {//枚举出有多少种砝码搭配情况

			int sum = 0;
			for (int j = 0;j < n;j++)
				if(i & (1 << j)) {
					sum += A[j];//将选中的玛法质量加起来
				}
			vis[sum] = 1;//标记相应质量的数组
			for (int j = 0 ;j < n;j++)
				if(sum-A[j]>=0)//减去一些砝码质量,如果质量大于0就将其标记
					vis[sum-A[j]] = 1;
		}

		cin >> q;
		while (q--) {
			cin >> Q;
			if(vis[Q])//直接在数组里找找到输出YES否则输出NO
				cout << "YES" << "\n";
			else
				cout << "NO" << "\n";
		}

	}
	return 0;
}
这篇关于涛涛的天平(二进制枚举)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!