一、闫氏DP分析法(从集合角度来分析)
核心思想:所有的DP问题基本都是有限集中最值、个数问题。
DP问题一般经历两个阶段(状态表示【化零为整】、状态计算【化整为零】)。
集合划分依据:寻找最后一个不同点。
二、例题演示
1.01背包问题
分析:
最后两个状态集合中选最大值
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int N1[] = new int[N+1];
int W[] = new int[N+1];
for(int i=1;i<=N;i++){
N1[i] = sc.nextInt();
W[i] = sc.nextInt();
}
int f[][] = new int[N+1][V+1];
for(int i=1;i<=N;i++){//代表行,即前i个数
for(int j=0;j<=V;j++){//代表列,即表示体积容量
f[i][j] = f[i-1][j];//不选该第i个时
if(j>=N1[i]){//选了第i个后,进行最大取值判断
f[i][j]=Math.max(f[i-1][j],f[i-1][j-N1[i]]+W[i]);
}
}
}
System.out.println(f[N][V]);
}
}
2.完全背包问题
分析
状态计算中:选择最大值
f[i][j]=Math.max(f[i-1][j],f[i-1][j-v]+w,f[i-1][j-2v]+2w,……)
等价于将上述的j变换成j-1后总体加上w
f[i][j-v]+w=Math.max(f[i-1][j-v],f[i-1][j-2v]+w,f[i-1][j-3v]+2w……)+w
故可以得到:Math.max(f[i-1][j],f[i][j-v]+wi)
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int V = sc.nextInt();
int N1[] = new int[N+1];
int W[] = new int[N+1];
for(int i=1;i<=N;i++){
N1[i]=sc.nextInt();
W[i]=sc.nextInt();
}
int[][] f = new int[N+1][V+1];
for(int i=1;i<=N;i++){
for(int j=0;j<=V;j++){
f[i][j]=f[i-1][j];
if(j>=N1[i]){
f[i][j]=Math.max(f[i-1][j],f[i][j-N1[i]]+W[i]);
}
}
}
System.out.println(f[N][V]);
}
}