首页 > 试题广场 >

双袋购物

[编程题]双袋购物
  • 热度指数:1260 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

一条马路上有 n 个点,从左到右从 1 到 n 编号。小明一开始在马路的最左边,一直往右走,一直走到马路的最右边,一直往右走,一直走到马路的最右边,中途不允许回头,只能往右走。

每个点上都有一个物品,第 i 个点的物品体积为 vi,价值为 wi,(注意:先输入体积再输入价值)小明有两个袋子,一号袋子和二号袋子,一号袋子体积为 A ,二号袋子体积为 B 。
最开始小明使用一号袋子,经过一个点的时候,他可以选择把点上的物品放入袋子中,但是袋中物品的总体积不能超过袋子的体积,也可以选择不拿这个物品。
在整个过程中的任意一个时刻,小明可以选择把一号袋子收起来,接下来使用二号袋子,一旦小明收起了一号袋子,之后他再也不能使用一号袋子,接下来的物品只能决策是否放入二号袋子中,且袋中的物品的总体积不能超过袋子容量。特别的,小明可以在最开始(遇到 1 号点之前)就换袋子,这样他全程都使用二号袋子 ;他也可以一直使用一号袋子,到最后也不收。
小明最后获得的价值为两袋子中物品价值和,问在最优策略下的最大价值。

数据范围:

输入描述:
输入第一行三个数 n , A , B。
接下里有 n 行,每行两个数 v_i , w_i 依次表示每个物品的体积和价值。


输出描述:
输出一个数,最大价值
示例1

输入

5 10 50
3 3
7 4
4 7
49 50
2 2

输出

60

说明

用一号袋子装1号和3号物品,之后收起一号袋子,用二号袋子装4号物品。 
public class Main {
  public static void main(String[] args) {
    java.util.Scanner sc = new java.util.Scanner(System.in);
    int n=sc.nextInt(), A=sc.nextInt(), B=sc.nextInt(), i, j, maxVal=0;
    int bagA[]=new int[A+5], bagB[]=new int[B+5], ansA[]=new int [n+5],
        ansB[]=new int[n+5], volume[]=new int[n+5], value[]=new int[n+5];
    for (i = 1; i <= n; ++i) {
      volume[i] = sc.nextInt();
      value[i] = sc.nextInt();
      for (j = A; j >= volume[i]; --j)//对袋子1进行动态规划
        bagA[j] = Math.max(bagA[j], bagA[j-volume[i]] + value[i]);
      ansA[i] = bagA[A];//ansA[i]:一直使用袋子1到第i个节点时的最大总价值
    }
    for (i = n; i > 0; --i) {//对袋子2进行动态规划,反向进行
      for (j = B; j >= volume[i]; --j)
        bagB[j] = Math.max(bagB[j], bagB[j-volume[i]] + value[i]);
      ansB[i] = bagB[B];//ansB[i]:使用袋子2从第i个节点到最后的最大总价值
    }
    for (i = 0; i <= n; ++i)//求在各个节点换袋子的决策能得到的最大总价值
      maxVal = Math.max(maxVal, ansA[i] + ansB[i+1]);
    System.out.println(maxVal);//时间复杂度:O(n*(A+B))
  }
}

编辑于 2018-07-04 16:23:05 回复(0)