洛谷P2392

题目链接

 

思路:

首先,不难看出,每类题目是独立的,因此仅考虑一类题目就行

要使总时间最小,显然要使左右脑所花费的时间尽可能地接近

我先想到了贪心,按时间排序,然后每次取最大的,将它分配给当前耗时最少的大脑

自信满满秒杀全WA了呜呜呜呜呜呜

 

其实可以发现,问题可以看出是,让一个大脑耗时不超过sumtime/2的情况下,让他的耗时最大(设为左脑)

那么问题便可以转化为01背包问题

每一个题目,要么选(左脑做),要么(不选),左脑只给他sumtime/2的时间,然后让左脑耗时最大

这样右脑耗时就最少

并且右脑>左脑,右脑的耗时便是答案

 

dp[ j ][ k ]表示对于前 j 个题目,在不超过 k 时间的情况下,左脑的最大耗时

dp[ j ][ k ] =  max( dp[ j - 1 ][ k ], dp[ j -1 ][ k - time[ j ] ] + time[ j ] )

第一维度可以去掉

dp[ k ] = max(dp[ k ], dp[ k - time[ j ] ] + time[ j ] )

代码如下

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 int s[4], t[30], ans, sum_time, dp[20000];
 8 bool cmp(int a, int b){
 9   return a > b;
10 }
11 
12 int main(){
13     for(int i = 0; i < 4; i++)
14         scanf("%d", s + i);
15     for(int i = 0; i < 4; i++){
16         sum_time = 0;
17         memset(dp, 0, sizeof(dp));
18         for(int j = 0; j < s[i]; j++){
19         scanf("%d", t + j);
20         sum_time += t[j];
21         }
22         for(int j = 0; j < s[i]; j++)
23         for(int k = sum_time / 2; k >= 0; k--)
24             if(k >= t[j])
25             dp[k] = max(dp[k], dp[k - t[j]] + t[j]);
26         ans += sum_time - dp[sum_time / 2];
27     }
28     printf("%d", ans);
29     return 0;
30 }

 

posted @ 2021-11-23 16:49  Endergarten  阅读(171)  评论(0)    收藏  举报