题目描述
涛涛有N个砝码和一个没有游标的天平,砝码可以放左边,也可以放右边,问可不可以测出所问的重量, 问的个数为Q个.
输入
第一行T,表示T组数据。 (1≤T≤5)
接下来
第一行一个数N,表示砝码个数。(1≤N≤20)
第二行N个数,表示砝码们的重量wi (1≤wi≤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; }