#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 4E3 + 10;
const long long INF = 1LL << 60;
short path[maxn][maxn];
long long f[maxn];
struct Node
{
long long d;
int num, sh;
};
int n, m, T, kase;
Node x[maxn], y[maxn];
bool cmpd(const Node &a, const Node &b)
{
return a.d < b.d;
}
bool cmpnum(const Node &a, const Node &b)
{
return a.num < b.num;
}
void solve(int i, int j)
{
if (i != 1) solve(i - 1, path[i][j]);
x[i].sh = y[j].num;
}
int main(int argc, char const *argv[])
{
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%I64d", &x[i].d), x[i].num = i;
scanf("%d", &m);
for (int i = 1; i <= m; i++)
scanf("%I64d", &y[i].d), y[i].num = i;
sort(x + 1, x + 1 + n, cmpd);
sort(y + 1, y + 1 + m, cmpd);
for (int i = 0; i <= max(n, m); i++)
f[i] = INF;
f[1] = abs(x[1].d - y[1].d);
for (int i = 2; i <= n; i++)
for (int j = min(i, m); j >= 1; j--)
{
if (f[j] < f[j - 1])
{
f[j] = f[j] + abs(x[i].d - y[j].d);
path[i][j] = j;
}
else
{
f[j] = f[j - 1] + abs(x[i].d - y[j].d);
path[i][j] = j - 1;
}
}
printf("%I64d\n", f[m]);
solve(n, m);
sort(x + 1, x + 1 + n, cmpnum);
for (int i = 1; i < n; i++)
printf("%d ", x[i].sh);
printf("%d\n", x[n].sh);
}
return 0;
}
分别对人和shelter从小到大排序之后再dp,这样可以消除后效性。
设f[i][j]表示第i个人放在第j个遮蔽物里,则有:f[i][j]=min(f[i-1][j],f[i-1][j-1])+abs(x[i]-y[j]);