HDU 5616:Jam's balance(背包DP)

http://acm.hdu.edu.cn/showproblem.php?pid=5616

题意:有n个物品,每个重量为w[i],有一个天平,你可以把物品放在天平的左边或者右边,接下来m个询问,问是否能用这些物品称出x的重量。

思路:如果只能放一边,那就是很简单的背包DP,现在考虑要放在左右两边,那么只需要逆着来做一遍就好了。因为如果放在左边就不能放在右边了,因此要分开算。

初始状态dp[0][0] = 1.

if(dp[i-1][j+w[i]] == 1) dp[i][j] = 1。(j + w[i] <= sum)

if(dp[i-1][j-w[i]] == 1) dp[i][j] = 1。(j - w[i] >= 0)

可以用滚动数组优化。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 25
 4 
 5 int dp[2][N*100], w[N];
 6 
 7 int main() {
 8     int t; scanf("%d", &t);
 9     while(t--) {
10         int n; scanf("%d", &n);
11         int sum = 0;
12         for(int i = 1; i <= n; i++) scanf("%d", &w[i]), sum += w[i];
13         memset(dp, 0, sizeof(dp));
14         int pre = 0, now = 1; dp[0][0] = 1;
15         for(int i = 1; i <= n; i++) {
16             for(int j = 0; j <= sum; j++) dp[now][j] = dp[pre][j];
17             for(int j = sum; j >= w[i]; j--) 
18                 if(dp[pre][j-w[i]]) dp[now][j] = 1;
19             for(int j = sum - w[i]; j >= 0; j--) 
20                 if(dp[pre][j+w[i]]) dp[now][j] = 1;
21             swap(pre, now);
22         }
23         int m; scanf("%d", &m);
24         while(m--) {
25             int x; scanf("%d", &x);
26             if(dp[pre][x]) puts("YES");
27             else puts("NO");
28         }
29     }
30     return 0;
31 }
原文地址:https://www.cnblogs.com/fightfordream/p/6588484.html