洛谷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 }

浙公网安备 33010602011771号