给定两个数组A
和B
,1
和1,000,000
之间的正数。我必须将a
中的每个整数A
与b
中的整数B
配对,以便最小化差值的绝对值之和。 A
和B
每个最多可包含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;
}
答案 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
的其余元素)。