寒假第六周 2.15 --- 2.21

新的一周^w^

2.15

hdu Greedy Tino

n个w[i],问能否分成相等的两堆,使得每一堆尽量大

不懂,题解说的是双塔dp

dp[i][j] 表示前i个搭成两个塔,差值为 j 的,这两个塔的高度的最大和

dp[i+1][j-v] = max(dp[i+1][j-v],dp[i][j]+v) //放在较高的那个塔上

dp[i+1][j+v] = max(dp[i+1][j+v],dp[i][j]+v)//放在较矮的那个塔

dp[i+1][j] = max(dp[i+1][j],dp[i][j]) 还可以不放

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const int INF = (1<<30)-1;
 9 const int maxn = 4005;
10 int n,w[maxn],dp[105][5005];
11 int c;
12 
13 void solve(){
14     for(int i = 0;i < 105;i++){
15         for(int j = 0;j < maxn;j++){
16             dp[i][j] = -INF;
17         }
18     }
19     //sort(w+1,w+n+1);
20     dp[0][0] = 0;
21     for(int i = 0;i < n;i++){
22         int v = w[i+1];
23         for(int j = 0;j <= 4000;j++){
24             if(dp[i+1][j+v] < dp[i][j]+v){
25                 dp[i+1][j+v] = dp[i][j]+v;
26             }
27             if(dp[i+1][abs(j-v)] < dp[i][j]+v){
28                 dp[i+1][abs(j-v)] = dp[i][j]+v;
29             }
30             if(dp[i+1][j] < dp[i][j]){
31                 dp[i+1][j] = dp[i][j];
32             }
33         }
34     }
35     if(dp[n][0] == 0 && c == 0) puts("-1");
36     else printf("%d\n",dp[n][0]/2);
37 }
38 
39 int main(){
40     int T;
41     scanf("%d",&T);
42     int kase = 0;
43     while(T--){
44         scanf("%d",&n);
45         c = 0;
46         for(int i = 1;i <= n;i++) {
47             scanf("%d",&w[i]);
48             if(w[i] == 0) c++;
49         }
50         printf("Case %d: ",++kase);
51         solve();
52     }
53     return 0;
54 }
View Code

 

搞不懂这种,和背包的那题,也是差值尽量小 的区别

明天再想>_<

 

你可能感兴趣的:(寒假第六周 2.15 --- 2.21)