首页 > 代码库 > 洛谷P2347 砝码称重 [2017年4月计划 动态规划01]

洛谷P2347 砝码称重 [2017年4月计划 动态规划01]

P2347 砝码称重

题目描述

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),

输入输出格式

输入格式:

输入方式:a1 a2 a3 a4 a5 a6

(表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个)

输出格式:

输出方式:Total=N

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

输入输出样例

输入样例#1:
1 1 0 0 0 0
输出样例#1:
Total=3

暴力算法略,这里只讲dp。
背包问题,每个砝码选或不选,显然01背包。
我们把砝码按照从小到大的顺序依次排开
f[i][j]表示前i个砝码能否组成质量j。
转移:f[i][j] = f[i-1][j] || f[i-1][j-w[i]],w[i]表示第i件物品(砝码)的价值(质量),k为第i件物品(砝码)的数量
常规压缩一维:f[j] = f[j] || f[j-k*w[i]]
代码中做了这样的处理:用i和j来共同控制第i件物品。
代码如下:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>inline int read(){	int x = 0;char ch = getchar();char c = ch;	while(ch > ‘9‘ || ch < ‘0‘)c = ch,ch = getchar();	while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘,ch = getchar();	if(c == ‘-‘)return -1 * x;	return x;}const int INF = 99999999999;int sum;int w[7] = {0,1,2,3,5,10,20};bool f[1010];int num[10];int ans;int main(){	for(int i = 1;i <= 6;i ++)	{		num[i] = read();		sum += num[i] * w[i];	}	f[0] = true;	for(int i = 1;i <= 6;i ++)	{		for(int j = 1;j <= num[i];j ++)		{			for(int k = sum;k >= w[i];k --)			{				if(f[k - w[i]])f[k] = true;			}		}	}	for(int i = 1;i <= sum;i ++)	{		if(f[i])ans ++;	}	printf("Total=%d", ans);	return 0;}

 

洛谷P2347 砝码称重 [2017年4月计划 动态规划01]