砝码称重问题

砝码称重问题


问题描述:

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总质量<=1000g),求出用他们能称出的质量的种类数(不包括质量为0的情况)。

输入:

a0  a1   a2   a3  a4   a5(表示六种砝码的枚数)

输出:

Total=N   /*N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况*/

输入样例:

1  1  0  0   0   0

输出样例:

Total=3                   /*表示可以称出1g,2g,3g三种不同的重量*/

解法一:

动态规划,visit[k]表示质量k能否被称出,1表示可以,0表示不可以。在处理第i个砝码时,visit [k– j*weight[i]] = 1 可以推知visit [k] = 1,weight[i]表示六种砝码的重量,j表示使用砝码的数量。

#include <iostream>
#include <memory.h>
using namespace std;

int total = 0;		//称出的质量的种类数
int weight[6] = {1,2,3,5,10,20};	//六种砝码
int a[6];			//每种砝码的枚数
char visit[1001];		//下标1--1000分别表示1--1000质量是否可以被称出。0表示不可以,1表示可以

int main()
{
	int i,j,k,sum=0;
	memset(visit,0,sizeof(visit));
	for(i=0;i<6;i++)		//读入每种砝码的枚数
	{
		cin>>a[i];
		sum+=a[i]*weight[i];
	}
	
	visit[0]=1;
	for(i=0;i<6;i++)			//遍历六种砝码
		for(j=1;j<=a[i];j++)		//使用砝码的枚数
			for(k=sum;k>=weight[i];k--)	//判断每种质量是否可以被称出
			{
				if(visit[k-weight[i]*j])
					visit[k]=1;
			}
			
	for(i=1;i<=sum;i++)	//统计
	{
		if(visit[i])
			total++;
	}
	
	cout<<"Total = "<<total<<endl;			
	return 0;
}

解法二:

1g的砝码有a0个(假设a0>0),则1g至a0 g的质量能够称出(k*weight[0],0<k<=a0),将其称出的质量存放在数组array中。可以在1g砝码计算结果的基础上分析2g砝码,其能称出的质量为array[j]+k*weight[1],0<=j<a1,0<k<=a1。由此可以推知第i个砝码能称出的质量为array[j]+k*weight[i],j为从0开始遍历已经称出质量的数组array的下标,0<k<=a[i]。同解法一一样使用visit[]去除重复的质量种类。

#include <iostream>
#include <memory.h>
#include <stdlib.h>
using namespace std;

int weight[6] = {1,2,3,5,10,20};	//六种砝码
int a[6];			//每种砝码的枚数
char visit[1001];		//下标1--1000分别表示1--1000质量是否可以被称出。0表示不可以,1表示可以

int main()
{
	int *array;		//称出的质量
	int i,j,k,sum=0,arraySum,newWeight,newSum;
	memset(visit,0,sizeof(visit));
	
	for(i=0;i<6;i++)		//读入每种砝码的枚数
	{
		cin>>a[i];
		sum+=a[i]*weight[i];
	}
	array=(int *)malloc(sizeof(array)*sum);	//已经成功称出的质量,最多能称出sum种质量,从array[1]开始
	memset(array,0,sizeof(array)*sum);
	arraySum=1;
	for(i=0;i<6;i++)			//遍历六种砝码
	{
		newSum=0;
		for(j=0;j<arraySum;j++)		//遍历array数组
		{
			for(k=1;k<=a[i];k++)	//使用砝码的枚数
			{
				newWeight=array[j]+k*weight[i];
				if(!visit[newWeight])
				{
					visit[newWeight]=1;
					array[arraySum+newSum]=newWeight;
					newSum++;
				}
			}
		}
		arraySum+=newSum;
	}
	cout<<"Total = "<<arraySum-1<<endl;			
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值