AcWing 12. 反推路径解释
原题链接
中等
作者:
季之秋
,
2021-04-12 22:38:38
,
所有人可见
,
阅读 280
import java.util.*;
public class Main{
static int N = 1010, n, m;
static int v[] = new int[N];
static int w[] = new int[N], f[][] = new int[N][N];
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for(int i = 1; i <= n; i ++){
v[i] = sc.nextInt();
w[i] = sc.nextInt();
}
for(int i = n ; i >= 1;i --){ // 以第i个数(后i个)开头的且总体积不超过j的方案取Max
for(int j = 0; j <= m; j ++){
f[i][j] = f[i+1][j]; // 不选i , 那就从i+1个里选,
if(j >= v[i]) f[i][j] = Math.max(f[i][j], f[i+1][j - v[i]] + w[i]); // 选i
}
}
// f[1][m] 表示以第1个数开头的且总体积不超过m的Max
int j = m;
for(int i = 1; i <= n; i ++){ // 字典序最小开始,
if(j >= v[i] && f[i][j] == f[i+1][j - v[i]] + w[i]){ // 表示选了第i个的状态,对应到上一个循环的最后一步
System.out.print(i+" ");
j -= v[i];
// 去掉i之后到下一个循环 就是f[i+1][j-v[i]] 表示的就是,从后i+1个数开始选,且总体积小于j-v[i]
// 因为最后一步是选了i所以j - v[i] 刚好表示后i+1个数的总体积
// 还可以换一个思路,我们选了第i个,去掉之后就是f[i][j] - w[i] = f[i+1][j - v[i]]
// 去掉之后就是到后i+1个数里选,
}
}
}
}