最小化差异的绝对值之和

时间:2013-05-21 00:43:36

标签: algorithm

An SPOJ question

给定两个数组AB11,000,000之间的正数。我必须将a中的每个整数Ab中的整数B配对,以便最小化差值的绝对值之和。 AB每个最多可包含5000个整数。

例如:

A=[10, 15, 13]B=[14,13, 12],最好的配对是(10, 12)(15, 14)(13, 13),因为|10-12|+|15-14|+|13-13|=3,这是我们最少的可以实现。因此,实现的最小总和是3

我认为这是一个动态的编程问题。

修改

数组可能大小不同,但每个最多可包含5000个元素。

我的代码:

#include <cmath>
#include <vector>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

static int DP[5002][5002], N, M, tmp;
vector<int> B, C;

int main()
{
    scanf("%d %d", &N, &M); memset(DP, -1, sizeof DP);
    B.push_back(0); C.push_back(0); DP[0][0]=0;
    for(int i=1; i<=N; ++i){scanf("%d", &tmp); B.push_back(tmp);} \\inputting numbers.
    for(int i=1; i<=M; ++i){scanf("%d", &tmp); C.push_back(tmp);}
    sort(B.begin(), B.end()); sort(C.begin(), C.end());         \\Sorting the two arrays.

    if(C.size()<=B.size()){                         \\Deciding whether two swap the order of arrays.
        for(int i=1; i<=N; ++i){
            for(int j=1; j<=M; ++j){
                if(j>i)break;
                if(j==1)DP[i][j]=abs(C[j]-B[i]);
                else{
                    tmp=DP[i-1][j-1]+abs(C[j]-B[i]);
                    DP[i][j]=(DP[i-1][j]!=-1)? min(tmp, DP[i-1][j]): tmp;
                }
            }
        }
        printf("%d\n", DP[N][M]);    \\Outputting the final result.
    }
    else{
        for(int i=1; i<=M; ++i){
            for(int j=1; j<=N; ++j){
                if(j>i) break;
                if(j==1)DP[i][j]=abs(C[i]-B[j]);
                else{
                    tmp=DP[i-1][j-1]+abs(C[i]-B[j]);
                    DP[i][j]=(DP[i-1][j]!=-1)? min(tmp, DP[i-1][j]): tmp;
                }
            }
        }
        printf("%d\n", DP[M][N]);
    }
    return 0;
}

1 个答案:

答案 0 :(得分:3)

Niels的评论阐明,如果数组大小相同,那么你应该对它们进行排序并配对值。我们可以在此基础上构建一般案例:

我假设第一个数组arr1的长度小于或等于第二个arr2的长度。如果不是,只需交换它们。首先,对两个数组进行排序,当只考虑子数组dp[A][B]arr1[A...](即来自 arr2[B...] arr1时,让A成为最小的差异从 arr2 到最后,转发和B。你有两个选择:

  • 配对 A B 。在这种情况下,您的总差异为|arr1[A]-arr2[B]| + dp[A+1][B+1]

  • 请勿使用 B 。请注意,在这种情况下,您再也不会考虑 B (因为如果您将 A B <配对/ em>到不同的元素,然后你可以交换两个对,总和会下降)。因此,您可以忽略 B ,答案为dp[A][B+1]

基础案例应该相当明显:

  • dp[length of arr1][length of arr2] = 0
  • dp[A][length of arr2] = infinity(无法配对arr1的其余元素)。