UPC Balance Scale 暴力模拟。

问题 C: Balance Scale

时间限制: 10 Sec  内存限制: 128 MB
提交: 153  解决: 8
[提交] [状态] [命题人:admin]

题目描述

You, an experimental chemist, have a balance scale and a kit of weights for measuring weights of powder chemicals.

For work efficiency, a single use of the balance scale should be enough for measurement of each amount. You can use any number of weights at a time, placing them either on the balance plate opposite to the chemical or on the same plate with the chemical. For example, if you have two weights of 2 and 9 units, you can measure out not only 2 and 9 units of the chemical, but also 11 units by placing both on the plate opposite to the chemical (Fig. C-1 left), and 7 units by placing one of them on the plate with the chemical (Fig. C-1 right). These are the only amounts that can be measured out efficiently.
 

Fig. C-1 Measuring 11 and 7 units of chemical

You have at hand a list of amounts of chemicals to measure today. The weight kit already at hand, however, may not be enough to efficiently measure all the amounts in the measurement list. If not, you can purchase one single new weight to supplement the kit, but, as heavier weights are more expensive, you'd like to do with the lightest possible.

Note that, although weights of arbitrary positive masses are in the market, none with negative masses can be found.

 

输入

The input consists of at most 100 datasets, each in the following format.

n m
a1 a2 ... an
w1 w2 ... wm
The first line of a dataset has n and m, the number of amounts in the measurement list and the number of weights in the weight kit at hand, respectively. They are integers separated by a space satisfying 1 ≤ n ≤ 100 and 1 ≤ m ≤ 10.

The next line has the n amounts in the measurement list, a1 through an, separated by spaces. Each of ai is an integer satisfying 1 ≤ ai ≤ 109, and ai ≠ aj holds for i ≠ j.

The third and final line of a dataset has the list of the masses of the m weights at hand, w1 through wm, separated by spaces. Each of wj is an integer, satisfying 1 ≤ wj ≤ 108. Two or more weights may have the same mass.

The end of the input is indicated by a line containing two zeros.

 

输出

For each dataset, output a single line containing an integer specified as follows.

If all the amounts in the measurement list can be measured out without any additional weights, 0.
If adding one more weight will make all the amounts in the measurement list measurable, the mass of the lightest among such weights. The weight added may be heavier than 108 units.
If adding one more weight is never enough to measure out all the amounts in the measurement list, -1.

 

样例输入

复制样例数据

4 2
9 2 7 11
2 9
6 2
7 3 6 12 16 9
2 9
5 2
7 3 6 12 17
2 9
7 5
15 21 33 48 51 75 111
36 54 57 93 113
0 0

样例输出

0
5
-1
5

题意:给定n个重量,m个砝码重量。问加一个砝码使得能够称出n个重量。问这个砝码的最小重量,可以是0,如果无解则输出-1. 还有,根据题意没有用4,6称出5的重量4<5<6,不存在这种情况,开始差点被误导了。。。

思路:砝码最多10个,则可以dfs3的10次方求出所有能求出来的重量。然后记录不能求出的数量。然后就是如何简单求出那个合法砝码的重量。想一下:如果这个砝码重量合法,则它一定能和能和sum【】(求的出来的)一起称出所有求不出来的。所以只需要用第一个求不出来的去找可以求出来的所有合法值,然后判断这些合法值能否将所有x【】(求不出来的)表示出来。记一个最小值即可。暴力模拟就行, 最大复杂度O(1e2*1e2*pow(3,10))


#include<bits/stdc++.h>
const int maxx=5e5+15;
#define ll long long
#pragma GCC optimize(2)
const ll mod=1e17+7;
using namespace std;
ll a[maxx],b[maxx];
ll sum[maxx];// 能称出的 
map<ll,ll>mp;//  标记,便于判断 
ll n,m;
ll cnt=0;
void dfs(ll deep,ll zuobian,ll youbian) //  
{
	if(deep==m+1) return ;
	sum[++cnt]=zuobian;
	sum[++cnt]=youbian;
	mp[zuobian]=1;
	mp[youbian]=1;
	if(zuobian>=youbian)  
	{
		mp[zuobian-youbian]=1;
		sum[++cnt]=zuobian-youbian;
	}
	else 
	{
		mp[youbian-zuobian]=1;
		sum[++cnt]=youbian-zuobian;
	}
 	dfs(deep+1,zuobian,youbian);
 	dfs(deep+1,zuobian+b[deep+1],youbian);
 	dfs(deep+1,zuobian,youbian+b[deep+1]);
}
int main()
{
	ll i,j,k,t;	
	while(~scanf("%lld%lld",&n,&m))
	{
		if(n==0&&m==0) break;
		ll x[300];// 不能称出的。 
		mp.clear();
		memset(sum,0,sizeof(sum));
		cnt=0;ll o=0;
		for(i=1;i<=n;i++) scanf("%lld",&a[i]);
		for(i=1;i<=m;i++) scanf("%lld",&b[i]);
		dfs(0,0,0);
		for(i=1;i<=n;i++)
		{
			if(mp[a[i]]!=1)
				x[++o]=a[i];
		}
		sort(x+1,x+1+o);
		sort(sum,sum+cnt);
		cnt=unique(sum,sum+cnt)-sum;// 去重排序 
		if(o==0) 
		{
			printf("0\n");
			continue;
		}
		ll maxl=1e18;
		for(i=1;i<=cnt;i++)
		{
			ll p1=abs(x[1]-sum[i]),p2=x[1]+sum[i];// 这是那两个可以加的砝码重量。 
			if(p1!=0)
			{
				ll flag=0; //判断加上它能不能求出所有的。 
				for(j=1;j<=o;j++)
				{
					if(mp[p1+x[j]]==1||mp[p1-x[j]]==1||mp[x[j]-p1]==1)
					continue;
					else 
					{
						flag=1;
						break;
					}
				}
				if(flag==0) maxl=min(p1,maxl);
			}
			if(p2!=0)// 懒得写函数,再来一遍呗 
			{
				p1=p2;
				int flag=0;
				for(j=1;j<=o;j++)
				{
					if(mp[p1+x[j]]==1||mp[p1-x[j]]==1||mp[x[j]-p1]==1)
					continue;
					else 
					{
						flag=1;
						break;
					}
				}
				if(flag==0) maxl=min(p1,maxl);
			}
		}
		if(maxl>mod) printf("-1\n");
		else 
		printf("%lld\n",maxl);
	}
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值