BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 貪心
阿新 • • 發佈:2017-10-04
++ http blank usaco ref ems 題目 ace 最大值
題目鏈接: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]; 1516 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 }
BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 貪心