zb's birthday
Time Limit:
3000 ms | Memory Limit: 65535 KB
Difficulty:
2
- describe
- Today is the fifth day of the seventh month of the lunar calendar, acm team member zb's birthday. zb is training with C Xiaojia and never in Wuhan. He wanted to buy something for the two brothers to celebrate their birthdays. After investigation, zb found that C Xiaojia and never liked to eat watermelons, and they were a pile of watermelons. Zb immediately decided to buy a pile of watermelons. When he was about to give the watermelons to C Xiaojia and never, he encountered a problem. Never and C Xiaojia did not live together, so he could only divide the watermelons into two piles for them. In order to be fair to everyone, he wanted to make the two The difference between the weights of the stacks is minimal. The weight of each watermelon is known, can you help him?
- enter
-
Multiple sets of test data (<=1500). The data ends with EOF.
The first line contains the number of watermelons N (1 ≤ N ≤ 20),
and the second line contains N numbers, W1, …, Wn (1 ≤ Wi ≤ 10000) represent the weight of each watermelon respectively - output
- Poor quality of output after splitting into two stacks
- sample input
-
5 5 8 13 27 14
- Sample output
- 3
- Solution 1: Dynamic Programming
- Add up all the watermelon weights and divide by two, use the 01 backpack to find the value closest to half the weight, this value is the weight of one of the piles, because the weight is very large, so it takes a lot of time
- Code:
1 #include <stdio.h> 2 #include <string.h> 3 #define max(a,b) a>b?a:b 4 using namespace std; 5 const int N = 100010; 6 int v[21]; 7 int dp[N]; 8 int main() { 9 int n; 10 while(scanf("%d", &n) != EOF) { 11 memset(dp, 0, sizeof(dp)); 12 int sum = 0; 13 for(int i = 0; i < n; i++) { 14 scanf("%d", &v[i]); 15 sum += v[i]; 16 } 17 int W = sum/2; 18 for(int i = 0; i < n; i++) { 19 for(int j = W; j >= v[i]; j--) { 20 dp[j] = max(dp[j], dp[j - v[i]] + v[i]); 21 } 22 } 23 printf("%d\n", sum - 2*dp[W]); 24 } 25 return 0; 26 }
Solution 2: Search + Pruning
This question is very heavy, so it takes a lot of time, but the number of watermelons is very small, so you can use search + pruning to do it
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n, maxn; 4 int w[21]; 5 int vs[21]; 6 void dfs(int cur, int sum, int W) { 7 if(cur == 0) { 8 maxn = max(maxn, sum); 9 return; 10 } 11 if(vs[cur] + sum < maxn) return; //剪枝 12 if(W >= w[cur]) dfs(cur-1, sum + w[cur], W - w[cur]); 13 dfs(cur-1, sum, W); 14 } 15 int main() { 16 while(scanf("%d", &n) != EOF) { 17 maxn = 0; 18 memset(vs, 0, sizeof(vs)); 19 int sum = 0; 20 for(int i = 1; i <= n; i++) { 21 scanf("%d", &w[i]); 22 sum += w[i]; 23 vs[i] += vs[i-1] + w[i]; 24 } 25 dfs(n, 0, sum/2); 26 printf("%d\n", sum - 2*maxn); 27 } 28 return 0; 29 }