HDU5616 Jam's balance(二进制枚举子集)

【二进制/位运算】 专栏收录该内容
13 篇文章 0 订阅

Problem Description

Jim has a balance and N weights. (1≤N≤20) The balance can only tell
whether things on different side are the same weight. Weights can be
put on left side or right side arbitrarily. Please tell whether the
balance can measure an object of weight M.

Input

The first line is a integer T(1≤T≤5), means T test cases. For each
test case : The first line is N, means the number of weights. The
second line are N number, i’th number wi(1≤wi≤100) means the i’th
weight’s weight is wi. The third line is a number M. M is the weight
of the object being measured.

Output

You should output the “YES”or”NO”.

Sample Input

1
2
1 4
3
2
4
5

Sample Output

NO
YES
YES

Hint

For the Case 1:Put the 4 weight alone For the Case 2:Put the 4 weight
and 1 weight on both side

思路

先说题意,现在有一个天平,有n个砝码,每个砝码有各自的重量,天平上的两端都可以放置砝码,并且通过天平只能知道两边是否平衡,给出了m组询问,每次询问一个重量,问这些砝码可否被称出来。

因为砝码只有20个,所以我们可以考虑一下枚举子集,枚举出砝码所有可以组成的情况,并且标记一下,然后就可以 O(1) O ( 1 ) 查询了。

代码

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int N=1000+20;
const int M=2000+10;
int a[N],vis[M];
int main()
{
    int t,n,m,x;
    scanf("%d",&t);
    while(t--)
    {
        mem(vis,0);
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
        }
        //枚举子集
        for(int i=0; i<(1<<n); i++) //二进制有n位
        {
            int cur=0;
            for(int j=0; j<n; j++)
            {
                if(i&(1<<j))
                    cur+=a[j];
            }
            vis[cur]=1;
            for(int j=0; j<n; j++)
            {
                if(cur-a[j]>=0)
                    vis[cur-a[j]]=1;
            }
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d",&x);
            if(vis[x])puts("YES");
            else puts("NO");
        }
    }
    return 0;
}
  • 1
    点赞
  • 3
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页

打赏

riba2534

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值