uvalive4987

来源:互联网 发布:图灵系列图书 知乎 编辑:程序博客网 时间:2024/06/05 05:40

题目大意:
有n支施工队在修一条笔直的高速公路,其中第i支队伍离告诉公路起点的距离是ai,

另外还有m个避难所,其中第i个避难所离高速公路的起点的距离是bi,给每只施工队分配一个避难所,距离是|ai,-bi|,求使得所有施工队移动距离的总距离最小,每个避难所最起码有一个施工队,打印每个施工队伍的避难所号

思路:
dp[i][j]表示前i只队伍到前j个避难所(前j个避难所每个都有施工队)所需要移动的最短距离。
那么dp[i][j] = min(dp[i - 1][j],dp[i][j]) + abs(a[i].d - b[i].d)
因为第i只队伍可以选择进去第j个避难所或者不进去。

代码:

#include <iostream>using namespace std;#include <cstring>#include <stdio.h>#include <algorithm>const int maxn = 4010;struct node {    int d,id,ans;}a[maxn],b[maxn];bool cmp(node a,node b) {    if(a.d == b.d)        return a.id < b.id;    return a.d<b.d;}bool cmp1(node a,node b) {    return a.id < b.id;}long long dp[maxn];int path[maxn][maxn];int n,m;void print(int i,int j) {    if(!i)        print(i - 1,path[i][j]);    a[i].ans = b[j].id;}int main() {    while(scanf("%d",&n) !=EOF) {        for(int i = 0; i < n; i++) {            scanf("%d",&a[i].d);            a[i].id = i;        }        scanf("%d",&m);        for(int i = 0; i <m ; i++) {            scanf("%d",&b[i].d);            b[i].id = i;        }        sort(a,a + n,cmp);        sort(b,b + m,cmp);        memset(dp,0x3f,sizeof(dp));        dp[0] = abs(a[0].d - b[0].d);        for(int i = 1; i < n; i++) {            for(int j = min(i,m - 1);j >= 0; j--) {//逆序可以保证每个避难所都有队伍            //第i个进入j                if(!j || dp[j] < dp[j - 1]) {//利用滚动数组 dp[i - 1][j] < dp[i - 1][j - 1]                 //前i - 1个可以进入j也可以不进入j                    dp[j] = dp[j] + abs(a[i].d - b[j].d);                    path[i][j] = j;                }                else {//dp[i - 1][j - 1] <= dp[i - 1][j]                    dp[j] = dp[j - 1] + abs(a[i].d - b[j].d);                    path[i][j] = j - 1;                }            }        }        printf("%lld\n",dp[m - 1]);        print(n - 1,m - 1);        sort(a,a + n,cmp1);        printf("%d",a[0].ans + 1);        for(int i = 1; i < n; i++)            printf(" %d",a[i].ans + 1);        printf("\n");    }    return 0;}
0 0
原创粉丝点击