zoukankan      html  css  js  c++  java
  • 【洛谷】【动态规划/背包】P1833 樱花

    【题目描述:】

    爱与愁大神后院里种了n棵樱花树,每棵都有美学值Ci。爱与愁大神在每天上学前都会来赏花。爱与愁大神可是生物学霸,他懂得如何欣赏樱花:一种樱花树看一遍过,一种樱花树最多看Ai遍,一种樱花树可以看无数遍。但是看每棵樱花树都有一定的时间Ti。爱与愁大神离去上学的时间只剩下一小会儿了。求解看哪几棵樱花树能使美学值最高且爱与愁大神能准时(或提早)去上学。

    【输入格式:】

    共n+1行:

    第1行:三个数:现在时间Ts(几点:几分),去上学的时间Te(几点:几分),爱与愁大神院子里有几棵樱花树n。

    第2行~第n+1行:每行三个数:看完第i棵树的耗费时间Ti,第i棵树的美学值Ci,看第i棵树的次数Pi(Pi=0表示无数次,Pi是其他数字表示最多可看的次数Pi)。

    【输出格式:】

    只有一个整数,表示最大美学值。

    输入样例#16:50 7:00 3
    2 1 0
    3 3 1
    4 5 4
    输出样例#111
    输入输出样例

    【算法分析:】

    01背包可以看做是只有一件物品的多重背包,所以可将三类背包问题化为两类:

    1. 多重背包
    2. 完全背包

    但多重背包直接做时间复杂度太大,所以需要二进制优化,此时如何处理完全背包问题?

    可以将完全背包的数量看做一个比较大,而数组中也存的开的数,比如9999,然后当做多重背包来做.

    【代码:】

     1 //P1833 樱花
     2 #include<iostream>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 const int MAXN = 1000000 + 1;
     7 const int INF = 9999;
     8 
     9 int n, T;
    10 int t[MAXN], c[MAXN], p[MAXN];
    11 int a[MAXN], b[MAXN], f[MAXN];
    12 struct Time {
    13     int h, min;
    14 }s, e;
    15 
    16 inline int read() {
    17     int x=0, f=1; char ch=getchar();
    18     while(ch<'0' || ch>'9') {
    19         if(ch == '-') f = -1;
    20         ch = getchar();
    21     }
    22     while(ch>='0' && ch<='9')
    23         x=(x<<3) + (x<<1) + ch-48, ch = getchar();
    24     return x * f;
    25 }
    26 
    27 int main() {
    28     s.h = read(), s.min = read();
    29     e.h = read(), e.min = read();
    30     n = read();
    31     T = e.min - s.min + (e.h - s.h) * 60;
    32     int cnt = 0;
    33     for(int i=1; i<=n; ++i) {
    34         t[i] = read(), c[i] = read(), p[i] = read();
    35         if(!p[i]) p[i] = INF;
    36         int s = 1;
    37         while(p[i] > s) {
    38             a[++cnt] = t[i] * s;
    39             b[cnt] = c[i] * s;
    40             p[i] -= s;
    41             s <<= 1;
    42         }
    43         if(p[i]) {
    44             a[++cnt] = t[i] * p[i];
    45             b[cnt] = c[i] * p[i];
    46         }
    47     }
    48     for(int i=1; i<=cnt; ++i)
    49         for(int j=T; j>=a[i]; --j)
    50             f[j] = max(f[j], f[j - a[i]] + b[i]);
    51     printf("%d
    ", f[T]);
    52 }
  • 相关阅读:
    二分思想判断数组中是否有两数和为sum
    VC中#pragma warning指令
    (转)预编译头文件
    成为一名优秀程序员所需要知道的那些事
    SetThreadAffinityMask设置使用多核CPU的哪个核心
    DirectX 3D 设备丢失(lost device)的处理
    转载 CreateWaitableTimer和SetWaitableTimer函数
    转赵青《剑侠情缘网络版》开发回顾
    转载使用PostThreadMessage在Win32线程间传递消息
    VC使用CRT调试功能检测内存泄漏
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9065567.html
Copyright © 2011-2022 走看看