1. 程式人生 > >BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 貪心

BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 貪心

++ 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];
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 }

BZOJ 2021 [Usaco2010 Jan]Cheese Towers:dp + 貪心