DP地狱训练 挤牛奶

1257: [DP地狱训练]挤牛奶

时间限制: 1 Sec  内存限制: 64 MB
提交: 917  解决: 260
[提交][状态][讨论版]

题目描述

小卡卡终于帮农夫John找到了走丢的那一头奶牛,John为了感谢小卡卡,不仅告诉了他在 Pascal山脉上可能存在Pascal圣地最大的宝藏,还说要请小卡卡喝牛奶。可是农夫John发现他家里所储藏的牛奶已经喝光了,所以要临时给奶牛挤奶。小卡卡实在是太好心了,说要帮农夫John一起挤牛奶。John答应了,他把他的n头奶牛中的n/2头(n是个偶数)分给小卡卡挤,他自己挤剩下的n/2头奶牛。但是每一头奶牛都有不同的产奶量,农夫John为了让小卡卡减轻负担,他希望他们两个所挤的牛奶的总量之差最小。小卡卡得知了每头奶牛的产奶情况之后很快就解决了这个问题。

输入

测试数据第一行一个整数n,n为偶数且小于100。表示有n头奶牛。 第二行n个整数分别给出每头奶牛的产奶量(产奶量的总和不超过2000)。

输出

输出小卡卡和农夫所挤的牛奶量的最小差值。

样例输入

6
7 9 2 6 4 2

依旧是判定性dp。

(用pascal书写效果更佳,因为数组下标可以为负数。)

(好吧C++也可以,先memset一块内存然后把某个指针赋值到该块内存的中间部分就行。)

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <vector>
 7  
 8 using namespace std;
 9  
10  
11 /*
12   f[i][j][k] : 前i个奶牛中j个分给了A,i - j个分给了B,A的牛奶量减去B的牛奶量的值为k。
13   f[i][j][k] = or { f[i - 1][j - 1][k - w[i]], f[i - 1][j][k + w[i]] }
14   f[0][0][0] = 1
15   f[i][0][-sum w[i]] = 1
16 */
17  
18 #define N 2500
19  
20 #define B (2 * N)
21  
22 int n, w, f[2][150][N * 5], p, sm;
23  
24 int main(){
25     f[0][0][B + 0] = 1;
26     scanf("%d", &n);
27     for(int i = 1 ; i <= n ; i ++){
28         p ^= 1;
29         scanf("%d", &w);
30         sm += w;
31         memset(f[p], 0, sizeof(f[p]));
32         f[p][0][B - sm] = 1;
33         for(int j = 1 ; j <= i ; j ++){
34             for(int k = -N ; k <= N ; k ++){
35                 f[p][j][B + k] = f[!p][j - 1][B + k - w] | f[!p][j][B + k + w];
36             }
37         }
38     }
39     for(int i = 0 ; i <= N ; i ++){
40         if(f[p][n / 2][B + i] | f[p][n / 2][B - i]){
41             printf("%d", i);
42             break;
43         }
44     }
45 }
View Code

 

posted @ 2017-08-08 15:53  KingSann  阅读(1413)  评论(0)    收藏  举报