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;
}

/**/

posted on 2012-07-22 08:32  getgoing  阅读(214)  评论(0编辑  收藏  举报

导航