BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 贪心
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2021
题意:
John要建一个奶酪塔,高度最大为m。
他有n种奶酪。第i种高度为h[i](一定是5的倍数),价值为w[i]。
一块高度>=t的奶酪被称为大奶酪,一个奶酪如果在它上方有大奶酪(多块只算一次),它的高度就会变成原来的4/5。
John想让他的奶酪他价值和最大,求这个最大值。
题解:
方法一:
dp + 贪心。
贪心:如果奶酪塔中有大奶酪,则大奶酪一定放在最上面。
(1)有大奶酪时:
枚举放在最上面的大奶酪k。
然后将所有奶酪的高度看作h[i]*4/5,塔的最大高度为m-h[k],跑一遍完全背包。
每一次的答案 = 完全背包的答案 + w[k],取最大。
(2)没大奶酪时:
最后再跑一遍没有大奶酪的完全背包,取最大。
方法二:
分成两种情况分别处理:
(1)塔中有大奶酪:
dp[i]表示高度为i,有大奶酪时的最大价值。
初始值:
先将dp设为-INF。
然后对于所有的大奶酪i,dp[h[i]] = max w[i]。
然后将所有高度看作原来的4/5,跑一遍完全背包。
(2)没有大奶酪:
高度为原先的高度,直接跑完全背包。
对于两种情况取最大就好。
AC Code(1):
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define MAX_N 105 6 #define MAX_M 1005 7 8 using namespace std; 9 10 int n,m,t; 11 int ans=0; 12 int w[MAX_N]; 13 int h[MAX_N]; 14 int dp[MAX_M]; 15 16 void read() 17 { 18 cin>>n>>m>>t; 19 for(int i=0;i<n;i++) 20 { 21 cin>>w[i]>>h[i]; 22 } 23 } 24 25 int cal_dp(int m,int u,int d) 26 { 27 int best=0; 28 memset(dp,0,sizeof(dp)); 29 for(int i=0;i<n;i++) 30 { 31 for(int j=h[i]*u/d;j<=m;j++) 32 { 33 dp[j]=max(dp[j],dp[j-h[i]*u/d]+w[i]); 34 best=max(best,dp[j]); 35 } 36 } 37 return best; 38 } 39 40 void solve() 41 { 42 for(int i=0;i<n;i++) 43 { 44 if(h[i]>=t) ans=max(ans,cal_dp(m-h[i],4,5)+w[i]); 45 } 46 ans=max(ans,cal_dp(m,1,1)); 47 } 48 49 void print() 50 { 51 cout<<ans<<endl; 52 } 53 54 int main() 55 { 56 read(); 57 solve(); 58 print(); 59 }
AC Code(2):
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 105 5 #define MAX_M 1005 6 7 using namespace std; 8 9 int n,m,t; 10 int ans=0; 11 int w[MAX_N]; 12 int h[MAX_N]; 13 int dp[MAX_M]; 14 15 void read() 16 { 17 cin>>n>>m>>t; 18 for(int i=0;i<n;i++) 19 { 20 cin>>w[i]>>h[i]; 21 } 22 } 23 24 int cal_dp(int u,int d) 25 { 26 int best=0; 27 for(int i=0;i<n;i++) 28 { 29 for(int j=h[i]*u/d;j<=m;j++) 30 { 31 dp[j]=max(dp[j],dp[j-h[i]*u/d]+w[i]); 32 best=max(best,dp[j]); 33 } 34 } 35 return best; 36 } 37 38 void solve() 39 { 40 memset(dp,0x80,sizeof(dp)); 41 for(int i=0;i<n;i++) 42 { 43 if(h[i]>=t) dp[h[i]]=max(dp[h[i]],w[i]); 44 } 45 ans=max(ans,cal_dp(4,5)); 46 memset(dp,0,sizeof(dp)); 47 ans=max(ans,cal_dp(1,1)); 48 } 49 50 void print() 51 { 52 cout<<ans<<endl; 53 } 54 55 int main() 56 { 57 read(); 58 solve(); 59 print(); 60 }