superoj732 砝碼稱重

題目描述

輸入格式

第一行爲兩個數,n 和 m 。
第二行爲 n 個數,表示這 n 個砝碼的重量。
第三行爲 m 個數,表示這 m 個物品的重量。

輸出格式

輸出 m 行,對於第 i 行,如果第 i 個物品能被稱出,輸出 “YES” 否則輸出“NO”。

樣例數據 1

輸入  [複製]

4 2 
1 2 4 8 
15 16

輸出

YES 
NO

備註

【數據範圍】
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;
} 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章