题意
app有两种大小,一个是下载安装包的大小d,一个是安装完之后变成大小s,这种app安装包很智能,安装的过程中是从安装包直接转化成了应用,整个过程不需要额外空间,只要手机有max(d,s)大小的空间就能装上去。现在为了尽可能安装多的app,要决定安装次序。
核心问题
找出贪心的顺序用01背包来dp
java代码
import java.util.Scanner;
import java.util.Stack;
import java.util.Vector;
public class Main {
static class app implements Comparable<app> {
public int d, s, id;
public app(int d, int s, int id) {
super();
this.d = d;
this.s = s;
this.id = id;
}
@Override
public int compareTo(app o) {//比较函数,比较的是安装先后次序
int a = s + Math.max(o.d, o.s);//先装a,然后装b,安装过程中所需空间的最大值
int b = o.s + Math.max(d, s);//ͬ同理是先安装b,然后安装a,肯定是要让安装空间峰值尽可能小
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
// public int compareTo(app o) {//这种贪心是错的
// if(s<o.s) return -1;
// if(s>o.s) return 1;
// if(d>o.d) return -1;
// if(d<o.d) return 1;
// return 0;
// }
@Override
public String toString() {
return "app [d=" + d + ", s=" + s + ", id=" + id + "]";
}
public int maxsize() {
return Math.max(d, s);
}
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
Integer n, c;
n = cin.nextInt();
c = cin.nextInt();
Vector<app> a = new Vector<>();
a.setSize(n);
for (int i = 0; i < n; i++) {
int d, s;
d = cin.nextInt();
s = cin.nextInt();
a.set(i, new app(d, s, i + 1));
}
a.sort(null);
int dp[][] = new int[n + 1][c + 1];//dp定义的是从前i个物品中选出总重量不超过j物品时候总价值最大值
for (int i = 0; i <= c; i++)
dp[0][c] = 0;
for (int i = 1; i <= n; i++) {
app u = a.elementAt(i - 1);
for (int j = 0; j <= c; j++) {
dp[i][j] = dp[i - 1][j];
if (j - u.s < 0)
continue;
if (c - (j - u.s) < u.maxsize())//剩余空间能否满足条件
continue;
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - u.s] + 1);
}
}
int size=c;//不一定能装满
for(int i=0;i<=c;i++)
if(dp[n][i]>dp[n][size]) size=i;
Stack<Integer> stk = new Stack<>();
for (int i = n; i >= 1; i--) {//寻找路径
app u = a.elementAt(i - 1);
if (size - u.s < 0)
continue;
if (dp[i - 1][size - u.s] == dp[i][size] - 1) {
size = size - u.s;
stk.push(u.id);
}
}
System.out.println(stk.size());
while (stk.isEmpty() == false) {
int id = stk.pop();
System.out.print(id);
if (stk.isEmpty())
System.out.print('\n');
else
System.out.print(' ');
}
cin.close();
}
}