1. 程式人生 > >洛谷-【動態規劃】-P2623 物品選取

洛谷-【動態規劃】-P2623 物品選取

題目背景

小X確信所有問題都有個多項式時間演算法,為了證明,他決定自己去當一次旅行商,在上路之前,小X需要挑選一些在路上使用的物品,但他只有一個能裝體積為m的揹包。顯然,揹包問題對小X來說過於簡單了,所以他希望你來幫他解決這個問題。

題目描述

小X可以選擇的物品有n樣,一共分為甲乙丙三類:

1.甲類物品的價值隨著你分配給他的揹包體積變化,它的價值與分配給它的體積滿足函式關係式,v(x) = A*x^2-B*x,A,B是每個甲類物品的兩個引數。注意每個體積的甲類物品只有一個。

2.乙類物品的價值A和體積B都是固定的,但是每個乙類物品都有個引數C,表示這個物品可供選擇的個數。

3.丙類物品的價值A和體積B也是固定的,但是每個丙類物品可供選擇的個數都是無限多個。

你最終的任務是確定小X的揹包最多能裝有多大的價值上路。

輸入輸出格式

輸入格式:

第一行兩個整數n,m,表示揹包物品的個數和揹包的體積;

接下來n行,每行描述一個物品的資訊。第一個整數x,表示物品的種類:

若x為1表示甲類物品,接下來兩個整數A, B,為A類物品的兩個引數;

若x為2表示乙類物品,接下來三個整數A,B,C。A表示物品的價值,B表示它的體積,C表示它的個數;

若x為3表示丙類物品,接下來兩個整數A,B。A表示它的價值,B表示它的體積。

輸出格式:

輸出檔案僅一行為一個整數,表示小X的揹包能裝的最大價值。

輸入輸出樣例

輸入樣例#1: 複製

1 0
1 1 1

輸出樣例#1: 複製

0

輸入樣例#2: 複製

4 10
2 1 2 1
1 1 2
3 5 2
2 200 2 3

輸出樣例#2: 複製

610

說明

對於50%的資料,只有乙和丙兩類物品;

對於70%的資料,1<=n<=100, 1<=m<=500,0<=A,B,C<=200;

對於100%的資料,1<=n<=100, 1<=m<=2000,0<=A,B,C<=200;

題解:混合揹包問題,對甲類物品來說是01揹包,對乙類物品來說是完全揹包,對丙類物品來說是多重揹包問題,如果對揹包問題足夠了解的話,本題很好解答,

import java.util.*;
/*
 *物品選取
 */
public class Main{
	static int a,b;
	public static int v(int x) {
		return (int) (a*x*x-b*x);
	}
	public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int m=in.nextInt();
        int[] dp=new int[2020];
        for(int i=1;i<=n;i++) {
        	int x=in.nextInt();
        	a=in.nextInt();
        	b=in.nextInt();
        	if(x==1) {
        		for(int j=m;j>=1;j--) {
        			for(int k=1;k<=j;k++) {
        				dp[j]=Math.max(dp[j-k]+v(k), dp[j]);
        			}
        		}
        	}else if(x==2) {
        		int c=in.nextInt();
        		for(int j=m;j>=b;j--) {
        			for(int k=1;k<=c;k++) {
        				if(j-k*b<0)
        					break;
        				dp[j]=Math.max(dp[j-k*b]+k*a, dp[j]);
        			}
        		}
        	}else if(x==3) {
        		for(int j=b;j<=m;j++) {
        			dp[j]=Math.max(dp[j-b]+a, dp[j]);
        		}
        	}
        }
        System.out.println(dp[m]);
	}
}