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

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;
}
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页