1. 程式人生 > >【洛谷】【動態規劃/背包】P1833 櫻花

【洛谷】【動態規劃/背包】P1833 櫻花

ios clas 但是 輸入 ostream 代碼 iostream pan time

【題目描述:】

愛與愁大神後院裏種了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\n", f[T]); 52 }

【洛谷】【動態規劃/背包】P1833 櫻花