首页 > 代码库 > [Offer收割]编程练习赛11 题目2 : 物品价值

[Offer收割]编程练习赛11 题目2 : 物品价值

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi现在有n个物品,每个物品都有一个价值。并且这n个物品总共有m个不同的属性,每个物品都具有其中若干属性。

小Ho要从中选出若干物品,满足每个属性都正好有奇数个物品拥有,且被选出的物品价值总和最大。你能帮助小Ho完成任务么?

输入

第一行一个数T(<=10),表示数据组数。对于每一组数据:

第一行两个数n,m(1<=n<=1000,m<=10)

接下来每两行描述一件物品。对于每一件物品:

第一行两个数v和s,表示其价值和所含属性数量(v<=100000,s<=m)

第二行s个数,表示该物品拥有的属性编号(1<=编号<=m)

输出

物品价值总和的最大值。

样例输入
1
3 2
2 1
1
2 1
2
5 2
1 2
样例输出
5

思路

状态压缩DP。

状态定义:

  dp[i][j]表示可选物品为[0, i]时,各属性奇偶状态为j的最大价值。

状态转移:

  不选择第i个物品时,dp[i][j] = max(dp[i][j], dp[i - 1][j]);

  选择第i个物品时,dp[i][s1] = max(dp[i][s1], dp[i - 1][j] + v[i]),其中s1 = j ^ p[i],对应于添加物品i后发生的状态转移。

代码

 1 import java.util.Arrays;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5 
 6     public static int resolve(int[] v, int[] p, int n, int m) {
 7         final int STATES = 1 << m;
 8         int[][] dp = new int[n + 1][STATES];
 9         for (int i = 0; i <= n; i++) {
10             Arrays.fill(dp[i], -1);
11         }
12 
13         dp[0][0] = 0;
14         for (int i = 1; i <= n; i++) {
15             for (int j = 0; j < STATES; j++) {
16                 if (dp[i - 1][j] < 0)
17                     continue;
18                 dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]);
19                 int s1 = j ^ p[i - 1];
20                 dp[i][s1] = Math.max(dp[i][s1], dp[i - 1][j] + v[i - 1]);
21             }
22         }
23 
24         return dp[n][STATES - 1];
25     }
26 
27     public static void main(String[] args) {
28         Scanner sc = new Scanner(System.in);
29         int t = sc.nextInt();
30         while (t-- > 0) {
31             int n = sc.nextInt();
32             int[] v = new int[n];
33             int[] p = new int[n];
34             int m = sc.nextInt();
35             for (int i = 0; i < n; i++) {
36                 v[i] = sc.nextInt();
37                 int pcnt = sc.nextInt();
38                 for (int j = 0; j < pcnt; j++) {
39                     p[i] |= (1 << (sc.nextInt() - 1));
40                 }
41             }
42 
43             System.out.println(resolve(v, p, n, m));
44         }
45     }
46 }

 

[Offer收割]编程练习赛11 题目2 : 物品价值