有一个箱子容量为v(正整数,0≤v≤20000),同时有n个物品(0<n≤30),每个物品有一个体积(正整数)。
要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。 输入:
箱子的容量v 物品数n
接下来n行,分别表示这n个物品的体积。
输出最多可以装多大容量
输入:
24
6
8
3
12
7
9
7
输出:24
/*
* 输入:
24
6
8
3
12
7
9
7
输出:24
同理求剩余最小容量,相减即可
*/
static int[] tj;
static int V;
static int[][] l;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
V = Integer.parseInt(scanner.nextLine());
int n = Integer.parseInt(scanner.nextLine());
min_v=V;
tj = new int[n];
l = new int[n + 1][V + 1];
for (int i = 0; i < n; i++) {
tj[i] = Integer.parseInt(scanner.nextLine());
}
vis = new boolean[n];
//法一.递归解法,效率不高
all(0);
System.out.println(min_v);
//法二:0 1 背包 动态规划
cal();
//法三:改进 动态规划
k();
}
static void k()
{
int b[] =new int[V+1];
for(int i=0;i<tj.length;i++)
{
for(int j=V;j>= tj[i];j--)
{
b[j] = Math.max(b[j], b[j-tj[i]]+tj[i]);
}
}
for(int i:b)
{
System.out.print(i+" ");
}
System.out.println();
System.out.println(b[V]);
}
static boolean[] vis;
static int min_v;
static void all(int i)
{
if(i==tj.length)
{
//find
int tmp=0;
for(int j=0;j<vis.length;j++)
{
if(vis[j])
{
tmp+=tj[j];
}
}
if(tmp<=V && min_v>V-tmp)
{
min_v=V-tmp;
}
return;
}
vis[i] =true;
all(i+1);
vis[i]=false;
all(i+1);
}
// 0 1 背包
static void cal() {
for (int j = 1; j < l[0].length; j++) {
for (int i = 1; i < l.length; i++) {
if (tj[i - 1] > j) {
l[i][j] = l[i - 1][j];
} else {
if (l[i - 1][j - tj[i - 1]] + tj[i - 1] > l[i - 1][j]) {
l[i][j] = l[i - 1][j - tj[i - 1]] + tj[i - 1];
} else {
l[i][j] = l[i - 1][j];
}
}
}
}
for (int[] i : l) {
for (int j : i) {
System.out.print(j + " ");
}
System.out.println();
}
get(V, tj.length);
}
static void get(int v, int i) {
if (i == 0 || v == 0)
return;
if (l[i][v] > l[i - 1][v]) {
get(v - tj[i - 1], i - 1);
System.out.print(i + " ");
} else {
get(v, i - 1);
}
}