二进制优化多重背包问题:樱花
樱花
题目背景
《爱与愁的故事第四弹·plant》第一章。
题目描述
爱与愁大神后院里种了 n n n 棵樱花树,每棵都有美学值 C i ( 0 ≤ C i ≤ 200 ) C_i(0 \le C_i \le 200) C i ( 0 ≤ C i ≤ 2 0 0 ) 。爱与愁大神在每天上学前都会来赏花。爱与愁大神可是生物学霸,他懂得如何欣赏樱花:一种樱花树看一遍过,一种樱花树最多看 P i ( 0 ≤ P i ≤ 100 ) P_i(0 \le P_i \le 100) P i ( 0 ≤ P i ≤ 1 0 0 ) 遍,一种樱花树可以看无数遍。但是看每棵樱花树都有一定的时间 T i ( 0 ≤ T i ≤ 100 ) T_i(0 \le T_i \le 100) T i ( 0 ≤ T i ≤ 1 0 0 ) 。爱与愁大神离去上学的时间只剩下一小会儿了。求解看哪几棵樱花树能使美学值最高且爱与愁大神能准时(或提早)去上学。
输入格式
共 n + 1 n+1 n + 1 行:
第 1 1 1 行:现在时间 T s T_s T s (几时:几分),去上学的时间 T e T_e T e (几时:几分),爱与愁大神院子里有几棵樱花树 n n n 。这里的 T s T_s T s ,T e T_e T e 格式为:hh:mm,其中 0 ≤ h h ≤ 23 0 \leq hh \leq 23 0 ≤ h h ≤ 2 3 ,0 ≤ m m ≤ 59 0 \leq mm \leq 59 0 ≤ m m ≤ 5 9 ,且 h h , m m , n hh,mm,n h h , m m , n 均为正整数。
第 2 2 2 行到第 n + 1 n+1 n + 1 行,每行三个正整数:看完第 i i i 棵树的耗费时间 T i T_i T i ,第 i i i 棵树的美学值 C i C_i C i ,看第 i i i 棵树的次数 P i P_i P i (P i = 0 P_i=0 P i = 0 表示无数次,P i P_i P i 是其他数字表示最多可看的次数 P i P_i P i )。
输出格式
只有一个整数,表示最大美学值。
样例 #1
样例输入 #1
1 2 3 4 6:50 7:00 3 2 1 0 3 3 1 4 5 4
样例输出 #1
提示
100 % 100\% 1 0 0 % 数据:T e − T s ≤ 1000 T_e-T_s \leq 1000 T e − T s ≤ 1 0 0 0 (即开始时间距离结束时间不超过 1000 1000 1 0 0 0 分钟),n ≤ 10000 n \leq 10000 n ≤ 1 0 0 0 0 。保证 T e , T s T_e,T_s T e , T s 为同一天内的时间。
样例解释:赏第一棵樱花树一次,赏第三棵樱花树 2 2 2 次。
这是一个普通背包,多重背包,完全背包的混合
其他的背包正常做就行,但由于平时都是把多重背包一个物品最多取n件拆成n个这种的一件物品。时间会消耗得很厉害。于是就出现了二进制优化:
一个正整数n,可以被分解成1,2,4,…,2(k-1),n-2 k+1的形式。其中,k是满足n-2^k+1>0的最大整数。
例如,假设给定价值为2,数量为10的物品,依据二进制优化思想可将10分解为1+2+4+3,则原来价值为2,数量为10的物品可等效转化为价值分别为1x2,2x2,4x2,3x2,即价值分别为2,4,8,6,数量均为1的物品。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <bits/stdc++.h> #define int long long using namespace std ; vector <int > t,c,p;int dp[100000 ]={0 };int T,n;int exchage (string st,string ed) { if (st[1 ]==':' )st="0" +st; if (ed[1 ]==':' )ed="0" +ed; int hs=stoi(st.substr(0 ,2 )),hed=stoi(ed.substr(0 ,2 )); int ms=stoi(st.substr(3 ,5 )),med=stoi(ed.substr(3 ,5 )); if (hed<hs)hed+=24 ; int ret=(hed-hs)*60 +med-ms; return ret; } signed main (void ) { string st,ed; cin >>st>>ed>>n; T=exchage(st,ed); for (int i=0 ;i<n;i++) { int tempt,tempc,tempp; cin >>tempt>>tempc>>tempp; if (tempp==1 || tempp==0 ) { t.push_back(tempt); c.push_back(tempc); p.push_back(tempp); } else if (tempp>1 ) { int x=0 ; while (tempp > pow (2 , x)) { t.push_back(tempt * pow (2 , x)); c.push_back(tempc * pow (2 , x)); p.push_back(1 ); tempp -= pow (2 , x); x++; } t.push_back(tempt * tempp); c.push_back(tempc * tempp); p.push_back(1 ); } } for (int i=0 ;i<t.size();i++) { if (p[i]==0 ) { for (int j=t[i];j<=T;j++) { dp[j]=max(dp[j],dp[j-t[i]]+c[i]); } } else { for (int j=T;j>=t[i];j--) { dp[j]=max(dp[j],dp[j-t[i]]+c[i]); } } } cout <<dp[T]<<endl ; return 0 ; }
Harbin Institute of Technology, Shenzhen 计算机科学与技术 本科在读