AcWing 273. 【Java】分级
原题链接
简单
作者:
tt2767
,
2020-01-09 01:32:12
,
所有人可见
,
阅读 951
/*
1. 状态定义: 最小化 S=∑Ni=1|Ai−Bi| ->
令C为A的顺序排序数组, f[i][j] = B[1...i] 已经确定并且以 B[i] == C[j] 为结尾的非递减最小值
令D为A的逆序排序数组, f[i][j] = B[1...i] 已经确定并且以 B[i] == D[j] 为结尾的非递增最小值
2. 状态计算: "依据倒数第二个数分配的是哪个C[i]将f[i][j]所代表的集合划分成j个不重不漏的子集" by yxc
f[i][j] = min( f[i-1][1~j] ) + abs(C[j] - A[i])
3. 边界: ?
4. 关键还是怎么去想“状态是怎么定义的?”这个问题,y总的分析法适合想到状态定义后怎么去看状态计算这一步
*/
import java.util.*;
public class Main{
void run(){
int n = jin.nextInt();
List<Integer> a = new ArrayList<>();
List<Integer> c = new ArrayList<>();
for (int i = 0 ; i < n ; i++){
int x = jin.nextInt();
a.add(x);
c.add(x);
}
c.sort((x,y)->(x-y));
int resAsc = dp(a, c, n);
Collections.reverse(a);
c.sort((x,y)->(y-x));
int resDesc = dp(a, c, n);
int res = Math.min(resAsc, resDesc);
System.out.println(res);
}
int dp(List<Integer> a, List<Integer> c, int n){
for (int i = 1 ; i <= n ; i++){
int minV = Integer.MAX_VALUE;
for (int j = 1 ; j <= n ; j++){
minV = Math.min(minV, f[i-1][j]);
f[i][j] = minV + Math.abs(c.get(j-1) - a.get(i-1));
}
}
int res = Integer.MAX_VALUE;
for (int i = 1 ; i <= n ; i++) res = Math.min(res, f[n][i]);
return res;
}
int maxN = 2002;
int[][] f = new int[maxN][maxN];
Scanner jin = new Scanner(System.in);
public static void main(String[] args) throws Exception {new Main().run();}
}
c.sort((x,y)->(y-x));
这句要删掉才行,只翻转a数组就行了,不然两次dp计算的情况是一样的