UVALive4987-Evacuation Plan(dp + 贪心)

来源:互联网 发布:淘宝外观侵权怎么处罚 编辑:程序博客网 时间:2024/05/22 10:23

题目链接

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2988

思路

这道题的关键就是贪心,将队伍坐标和避难所坐标都从小到大排序,然后再进行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] = xconst 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;}
0 0
原创粉丝点击