2004选拔赛 最小值
给出S和T个整数集合,分别含有n和m个元素(n<=m<=500),问
的最小值。
如果a>b && c>d,有|a-c|=|b-d| >= |a-d| + |b-c|(不妨设c>a,然后对d与a,b的大小讨论,可以去掉绝对值符号证明),要对S和T排序。
动态规划,if ( i == j) f[i,j] = f[i-1, j-1] + abs( s[i] - t[j] ) ,所以边界条件有 f[0,0] = 0;
if (j > i) f[i, j] = min( f[i, j-1], f[i-1, j-1]+abs( s[i] - t[j] ) ),所以另一个边界条件是f[0, k] = 0 (k > 0).
记忆化搜索。
# include <stdio.h> # include <stdlib.h> # include <math.h> # define N 500 + 5 int n, m; int s[N], t[N]; int f[N][N]; int min(int x, int y) { return x < y ? x : y; } int cmp(const void *x, const void *y) { return *(int*)x > *(int*)y ? 1 : -1; } int dp(int i, int j) { if (f[i][j] >= 0) return f[i][j]; if (i == 0) return f[i][j] = 0; if (i == j) return f[i][j] = dp(i-1, j-1) + abs(s[i]-t[j]); return f[i][j] = min(dp(i, j-1), dp(i-1, j-1)+abs(s[i]-t[j])); } void init(void) { int i; scanf("%d%d", &n, &m); for (i = 1; i <= n; ++i) scanf("%d", &s[i]); for (i = 1; i <= m; ++i) { memset(f[i], -1, sizeof(f[i])); scanf("%d", &t[i]); } qsort(s+1, n, sizeof(s[0]), cmp); qsort(t+1, m, sizeof(t[0]), cmp); } void solve(void) { int i, j; int ans = dp(n, m); printf("%d\n", ans); } int main() { int T; scanf("%d", &T); while (T--) { init(); solve(); } return 0; }
/**/