#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]);
时间: 2024-10-11 03:22:35