AcWing 12. 背包问题求具体方案
原题链接
中等
作者:
tt2767
,
2020-01-12 23:17:23
,
所有人可见
,
阅读 809
/*
1. 状态定义: f[i][j] 表示选完1..i时 且 状态 <= j时的最大值,因为要保留路径,所以不压缩
2. 状态计算: ~
3. 边界: f[~][~] = 0
*/
import java.util.*;
import java.util.stream.*;
public class Main{
void run(){
int N = jin.nextInt();
int V = jin.nextInt();
for (int i = 1 ; i <= N ; i++) {
v[i] = jin.nextInt();
w[i] = jin.nextInt();
}
for (int i = N; i >= 1; i--){
for (int j= V; j >= v[i] ; j--)
f[i][j] = Math.max(f[i+1][j], f[i+1][j - v[i]] + w[i]); // 从后向前是 i+1
// 这里要把所有情况都写上,因为可能有不选但字典序最小的
for (int j = v[i]-1 ; j >= 0 ; j--) f[i][j] = f[i+1][j];
}
for (int i = 1; i<= N; i++){
if ( V>= v[i] && f[i][V] == f[i+1][V-v[i]] + w[i]) { // 判断坐标合法
path.add(i);
V -= v[i]; // 变成当前层最值
}
}
String res = String.join(" ", path.stream().map(x->String.valueOf(x)).collect(Collectors.toList()));
System.out.println(res);
}
int maxN = 1002;
int[] v = new int[maxN];
int[] w = new int[maxN];
int[][] f= new int[maxN][maxN];
List<Integer> path = new ArrayList<Integer>();
Scanner jin = new Scanner(System.in);
public static void main(String[] args) {new Main().run();}
}