砝码问题

(1)给出N个指定质量的砝码,和一个重M的物体,请指出称此物体所需要的最少砝码数量?

    注:称量方法既可以为砝码加砝码形式,也可以为砝码减砝码形式

   参数形式:N(砝码数量)    M(物体重量)

                     M1(砝码1质量)

                     ......

                     Mn(砝码1质量)

#include <map>
#include <vector>
#include <iostream>
using namespace std;

void fInsert(int weigh, int count, map<int,int> &wMap)
{
	if(weigh == 0)
	{
		return;
	}
	auto it = wMap.find(weigh);
	if(it == wMap.end())
	{
		wMap.insert(pair<int,int>(weigh,count));
	}
	else if(count < it->second)
	{
		it->second = count;
	}
}
int main()
{
	int m, n;
	cin>>n>>m;

	vector<int> weightVec;
	map<int,int> weighMap;
	for(int weight,i=0; i<n; i++)
	{
		cin>>weight;
		weightVec.push_back(weight);
	}

	for(int i=0; i<weightVec.size(); i++)
	{
		map<int,int> addWeighMap;
		addWeighMap.insert(pair<int,int>(weightVec[i],1));
		for(auto iter=weighMap.begin(); iter!=weighMap.end(); iter++)
		{
			int weigh = iter->first - weightVec[i];
			int count = iter->second + 1;
			if(weigh < 0)
			{
				weigh = 0 - weigh;
			}
			fInsert(weigh, count, addWeighMap);
			weigh = iter->first + weightVec[i];
			fInsert(weigh, count, addWeighMap);
		}
		for(auto iter = addWeighMap.begin(); iter != addWeighMap.end(); iter++)
		{
			fInsert(iter->first, iter->second, weighMap);
		}
	}

	auto it = weighMap.find(m);
	if(it != weighMap.end())
	{
		cout<<"最少需砝码数量:"<<it->second<<endl;
	}
	else
	{
		cout<<"使用所给砝码无法称出所给重量物体!"<<endl;
	}
}


(2)梅氏砝码问题,其叙述如下: 
若有n个砝码,重量分别为M1,M2,……,Mn,且能称出从1到(M1+M2+……+Mn)的所有重量,则再加一个砝码,重量为Mn+1=(M1+M2+……+Mn)*2+1,则这n+1个砝码能称出从1到 (M1+M2+……+Mn+Mn+1)的所有重量。

我们尝试构造这样一个序列。从1开始逐次拓展,使可称重的重量不断向后延伸:

1                 1                           1                                      1

1 3              1+3=4                   3-1=1+1                           1~4

1 3 9           1+3+9=13             9-(1+3)=(1+3)+1              1~13

1 3 9 27      1+3+9+27=40       27-(1+3+9)=(1+3+9)+1    1~40

......

如当前所有砝码重量和为S,则S是这些砝码能称的最大重量。考虑下一个扩展的砝码重量X,那么容易想到,扩展后X-S~X+S都可以称量。考虑节省做法,应该使X-S=S+1,这样可以推得下一个砝码质量。

S+1=X-S ——> X = 2S+1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值