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 }