题目链接
思路
这道题的关键就是贪心,将队伍坐标和避难所坐标都从小到大排序,然后再进行dp。从小到大进行排序基于:若a < b且c < d,则|a - c| + |b - d| < |a - d| + |b - c|
定义状态d[i][j]:第i只队伍进到避难所j里面,并且i和j之前的队伍和避难所都已经被分配完
转移方程:d[i][j] = min(d[i - 1][j - 1], d[i - 1][j]) + dist(a[i], b[j])
细节
滚动数组
代码
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl
#define CLR(a, x) memset(a, x, sizeof(a))
#define FILL(a, n, x) for (int i = 0; i < n; i++) a[i] = x
const int maxn = 4000 + 5;
const LL INF = 0x3f3f3f3f;
int n, m, p[maxn][maxn];
LL d[maxn];
struct node {
int id, d, ans;
} a[maxn], b[maxn];
bool cmp(node x, node y) {
if (x.d == y.d) return x.id < y.id;
return x.d < y.d;
}
bool cmp2(node x, node y) {
return x.id < y.id;
}
void print(int x, int y) {
if (x) print(x - 1, p[x][y]);
a[x].ans = b[y].id;
}
int main() {
while (~scan(n)) {
for (int i = 0; i < n; i++) {
scan(a[i].d);
a[i].id = i;
}
scan(m);
for (int i = 0; i < m; i++) {
scan(b[i].d);
b[i].id = i;
}
sort(a, a + n, cmp);
sort(b, b + m, cmp);
memset(d, INF, sizeof(d));
d[0] = abs(a[0].d - b[0].d);
for (int i = 1; i < n; i++) {
for (int j = min(m - 1, i); j >= 0; j--) {
LL dist = abs(a[i].d - b[j].d);
if (j > 0 && d[j - 1] < d[j]) {
d[j] = d[j - 1] + dist;
p[i][j] = j - 1;
} else {
d[j] += dist;
p[i][j] = j;
}
}
}
printf("%lld\n", d[m - 1]);
print(n - 1, m - 1);
sort(a, a + n, cmp2);
printf("%d", a[0].ans + 1);
for (int i = 1; i < n; i++) printf(" %d", a[i].ans + 1);
pl();
}
return 0;
}