• 洛谷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;
    }
    
  • 相关阅读:
    排序算法的实现
    图——广度优先遍历(邻接矩阵存储)
    最大子列和问题-4种解法
    PATB 1015. 德才论 (25)
    PATB 1018. 锤子剪刀布
    PATB 1019. 数字黑洞 (20)
    常用协议的默认端口号
    统一资源定位符URL
    hdoj1009 FatMouse' Trade——贪心算法
    hdoj2037 贪心算法——今年暑假不AC
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6723080.html
Copyright © 2020-2023  润新知