砝码称重问题
问题描述:
设有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;
}