• 采药升级版


    【问题描述】
    辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”如果你是辰辰,你能完成这个任务吗?
    【输入文件】
    输入文件medic2.in 的第一行包含两个正整数N,M。M 表示总共能够用来采药的时间,N 代表山洞里的草药的数目。接下来的N 行每行包括两个的整数,分别表示采摘某株草药的时间Ti 和这株草药的价值Vi。
    【输出文件】
    输出文件为medic2.out,仅包含一个整数表示规定时间内可以采到的草药
    的最大总价值。
    【输入样例】
    3 9
    10 10
    8 1
    1 2
    【输出样例】
    3

    【数据规模和约定】
    50%的数据中N,M ≤ 1000;
    100%的数据中N,M ≤ 100000,Ti,Vi ≤10。

    分析:这道题乍一看就是一个01背包,然而看看数据范围发现会TLE。那怎么办呢?这是又在数据范围里看到了一个希望:Ti,Vi ≤10。这就说明最多有100种物品,因此一定会有物品重复。那么这就转化为一个多重背包了。用二进制优化,这道题就解了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 typedef long long ll;
     8 const int maxn = 1e5 + 5; 
     9 int T, m;
    10 int c[maxn], v[maxn], dp[maxn];
    11 ll read()
    12 {
    13     ll ans = 0;
    14     char ch = getchar(), last = ' ';
    15     while(ch < '0' || ch > '9')        //处理非法字符 
    16     {
    17         last = ch; ch = getchar();
    18     }
    19     while(ch >= '0' && ch <= '9')
    20     {
    21         ans = ans * 10 + ch - '0'; ch = getchar();    
    22     }
    23     if(last == '-') ans -= ans;
    24     return ans;
    25 }
    26 int vis[15][15], num = 0;
    27 void hebing(int C, int V,int GS)    //二进制优化 
    28 {
    29     int x = 1;
    30     while(GS - x > 0)
    31     {
    32         c[++num] = x * C;
    33         v[num] = x * V;
    34         GS -= x;
    35         x <<= 1;
    36     }
    37     c[++num] = GS * C;
    38     v[num] = GS * V;
    39     return;
    40 }
    41 void dp()
    42 {
    43     for(int i = 1; i <= m; ++i)
    44     {
    45         int a = read(), b = read();
    46         vis[a][b]++;         //统计每种物品有多少个 
    47     }
    48     for(int i = 0; i <= 10; ++i)
    49         for(int j = 0; j <= 10; ++j)
    50             if(vis[i][j]) {hebing(i, j, vis[i][j]);}
    51     for(int i = 1; i <= num; ++i)        //按01背包做 
    52     {
    53         for(int j = T; j >= c[i]; --j) dp[j] = max(dp[j], dp[j - c[i]] + v[i]);
    54     }
    55     printf("%d
    ", dp[T]);
    56 }
    57 int main()
    58 {
    59     m = read(); T = read();
    60     dp();
    61     return 0;
    62 }
  • 相关阅读:
    VMware Workstation CentOS7 Linux 学习之路(2)--.net core环境安装
    VMware Workstation CentOS7 Linux 学习之路(1)--系统安装
    Castle IOC概念理解
    Visual Studio Nuget还原步骤
    Js中分号使用总结
    ABP理论学习之依赖注入
    C# 中字段和属性的使用时机
    C#基础知识梳理系列
    .Net 中的IL中间语言基本语法
    项目工程结构说明(Internal)
  • 原文地址:https://www.cnblogs.com/mrclr/p/8496724.html
Copyright © 2020-2023  润新知