第一行为两个数,n 和 m 。
第二行为 n 个数,表示这 n 个砝码的重量。
第三行为 m 个数,表示这 m 个物品的重量。
题目描述
输入格式
输出格式
输出 m 行,对于第 i 行,如果第 i 个物品能被称出,输出 “YES” 否则输出“NO”。
样例数据 1
备注
【数据范围】
30% 数据,n<=10;
50% 数据为随机数据;
100% 数据保证:1<=n<=24, 1<=m<=10。所有重量的绝对值在 1014 以内。
分析: 暴力搜索(3^n)
分治 每个砝码可以放左放右不放 把24个砝码分成俩份
一半求出3^12种可能情况,存在hash中
另一半求出3^12种可能,到hash中找有没有匹配的另一半
时间复杂度O(2* 3^(n/2))
代码
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
//map <long long,bool> q;
long long n,m;
long long fama[50];
long long thing[50];
long long size;
long long p[1000000];
long long hash[2000000];
long long read()
{
long long k=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+c-'0'; c=getchar();}
return k*f;
}
long long gethash(long long x)
{
long long u=((x%1000007)+1000007)%1000007;
while(hash[u]&&hash[u]!=x) u++;
// hash[u]=x;
return u;
}
int main()
{
// freopen("lx.in","r",stdin);
// freopen("lx.out","w",stdout);
long long i,j,k;
n=read();
m=read();
for(i=1;i<=n;i++)
{
fama[i]=read();
}
for(i=1;i<=m;i++)
{
thing[i]=read();
}
p[1]=0;
size=1;
for(i=1;i<=n/2;i++)
{
long long dd=size;
for(j=1;j<=dd;j++)
{
p[++size]=p[j]+fama[i];
p[++size]=p[j]-fama[i];
}
}
for(i=1;i<=size;i++)
{
hash[gethash(p[i])]=p[i];
}
p[1]=0;
size=1;
for(i=n/2+1;i<=n;i++)
{
long long dd=size;
for(j=1;j<=dd;j++)
{
p[++size]=p[j]+fama[i];
p[++size]=p[j]-fama[i];
}
}
for(j=1;j<=m;j++)
{
bool oo=0;
for(i=1;i<=size;i++)
if(hash[gethash(thing[j]-p[i])]==thing[j]-p[i])
{oo=1;break;}
if(oo) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}