nyoj 0325 zb's birthday (split)

nyoj 0325 zb's birthday

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 }
View Code

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 }
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325020366&siteId=291194637