zoukankan      html  css  js  c++  java
  • 【dp】砝码称重

    砝码称重

    来源:NOIP1996(提高组)  第四题

    【问题描述】

        设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),用他们能称出的重量的种类数。

    【输入文件】

      a1  a2  a3  a4  a5  a6

        (表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个,中间有空格)。

    【输出文件】

      Total=N

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

    【输入样例】

        1 1 0 0 0 0

    【输出样例】

        TOTAL=3

    【问题分析】

    把问题稍做一个改动,已知a1+a2+a3+a4+a5+a6个砝码的重量w[i], w[i]∈{ 1,2,3,5,10,20} 其中砝码重量可以相等,求用这些砝码可称出的不同重量的个数。

    这样一改就是经典的0/1背包问题的简化版了,求解方法完全和上面说的一样,这里就不多说了,只是要注意这个题目不是求最大载重量,是统计所有的可称出的重量的个数。


    设dp[1000]数组为标记数组。当dp[i]=0时,表示质量为i的情况,目前没有称出;当dp[i]=1时,表示质量为i的情况已经称出。

      本题目中有多个砝码,我们顺序处理每一个砝码。

      当处理第j个砝码,质量为wj时,有下列推导公式:

                    


     1 #include<iostream>
     2 #include<algorithm>
     3 #include<string>
     4 #include<vector>
     5 #include<set>
     6 #include<queue>
     7 #include<map>
     8 #include<stack>
     9 #include<iterator>
    10 #include<cstdio>
    11 #include<cstring>
    12 #include<cstdlib>
    13 #include<cmath>
    14 using namespace std;
    15 typedef long long ll;
    16 typedef unsigned long long ull;
    17 #define clr(c) memset(c, 0, sizeof(c));
    18 #define pi acos(-1.0)
    19 const int INF = 0x3f3f3f3f;
    20 const int mod = 1e9 + 7;
    21 const double eps = 1e-8;
    22 typedef struct point{
    23     int x, y;
    24     bool operator < (const point& p) const{
    25         if (x == p.x) return y < p.y;
    26         else return x < p.x;
    27     }
    28     bool operator >(const point& p) const{
    29         return p < *this;
    30     }
    31 }p;
    32 int n[10];
    33 int w[10] = {1, 2, 3, 5, 10, 20};
    34 int dp[2005];
    35 int sum, ans;
    36 
    37 int main(){
    38     while(~scanf("%d%d%d%d%d%d", &n[0], &n[1], &n[2], &n[3], &n[4], &n[5])){
    39         sum = 0;
    40         for(int i = 0; i < 6; i++) sum += w[i]*n[i];
    41         memset(dp, 0, sizeof(dp));
    42         dp[0] = 1;
    43         for(int i = 0; i < 6; i++){
    44             for(int j = 0; j < n[i]; j++){
    45                 for(int k = sum; k >= w[i]; k--){
    46                     dp[k] = dp[k-w[i]];
    47                 }
    48             }
    49         }
    50         ans = 0;
    51         for(int i = 0; i < sum; i++){
    52             ans += dp[i];
    53         }
    54         printf("%d
    ", ans);
    55     }
    56 
    57     return 0;
    58 }
  • 相关阅读:
    《C++反汇编与逆向分析技术揭秘》--构造函数 读书笔记
    《C++反汇编与逆向分析技术揭秘》--虚函数 读书笔记
    VPP-main() 源码学习
    【转】几种TCP连接中出现RST的情况
    动态追踪学习
    RCU学习总结
    内核栈回溯原理学习应用
    《C++反汇编与逆向分析技术揭秘》--单类继承 读书笔记
    C# 防火墙操作之创建规则
    C# 防火墙操作之特定程序
  • 原文地址:https://www.cnblogs.com/miaowTracy/p/5932600.html
Copyright © 2011-2022 走看看