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;

}

/**/

你可能感兴趣的:(值)