涉及算法:dp
题目描述:给定一个目标cash数目m,现在你拥有n种不同的cash分别编号1~n,不同种类的cash有着不同的面值v、数目a,现在从你所拥有的cash中任意抽取一些,使得总的cash数最接近m并且不大于m。
题目分析:很明显的 多重背包问题
代码如下:
题目描述:给定一个目标cash数目m,现在你拥有n种不同的cash分别编号1~n,不同种类的cash有着不同的面值v、数目a,现在从你所拥有的cash中任意抽取一些,使得总的cash数最接近m并且不大于m。
题目分析:很明显的 多重背包问题
代码如下:
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class Main_1276 {
static int max;//目标cash数
static int sort;//cash的面额种类数目
static int[][] v;//v[i][0]:编号为i的cash的数目,v[i][1]:编号为i的cash的面额
static int[] dp;//dp[i]:目标cash数目为i时,所能到达的最大的cash数目
static int[] count;//
public static void main(String[] args) throws IOException {
Scanner in=new Scanner(System.in);
while(in.hasNextInt()){
max=in.nextInt();
sort=in.nextInt();
v=new int[sort+1][2];
dp=new int[max+1];
count=new int[max+1];
for(int i=1;i<=sort;i++){
v[i][0]=in.nextInt();
v[i][1]=in.nextInt();
}
// dp();
// dp2();
dp3();
System.out.println(dp[max]);
}
}
//自顶向下,TLE
static int dp(int res,int x){ //剩余值为res且只考虑第0~x种的面额所能得到 的最大值
if(x==-1 || res==0) return 0;
int q=-1;
for(int i=0;i<=v[x][0];i++){
if(res-v[x][1]*i>=0){
q=Math.max(q,v[x][1]*i+dp(res-v[x][1]*i,x-1));
}
}
return q;
}
//TLE
//dp[i][j]:只考虑编号为1~i的cash,目标cash为j是,所能到达的最大的cash数目
static void dp2()
{
int dp3[][]=new int[sort+1][max+1];
int tmp;
for(int i=1;i<=sort;i++)
{
tmp=-1;
for(int j=v[i][1];j<=max;j++)
{
for(int k=0;k<=v[i][0];k++)
{
if(j<k*v[i][1])
{
break;
}
else
{
if(dp3[i-1][j-k*v[i][1]]+k*v[i][1]>tmp)
{
tmp=dp3[i-1][j-k*v[i][1]]+k*v[i][1];
}
}
}
dp3[i][j]=tmp;
}
}
System.out.println(dp3[sort][max]);
}
//AC
static void dp3(){
for(int i=0;i<sort;i++)
{
Arrays.fill(count, 0);
for(int j=v[i][1];j<=max;j++)
if(dp[j]<dp[j-v[i][1]]+v[i][1] && count[j-v[i][1]]<v[i][0])
{
dp[j] = dp[j-v[i][1]]+v[i][1];
count[j]=count[j-v[i][1]]+1;
}
}
}
}