LA 4987 背包

题意:

有n个施工队,给定他们的位置,有m个防空洞,给定位置,求将施工队放到m个防空洞里面,最少的总距离?

n<=4000

分析:

dp[i][j] 前 i 个施工队,放到前 j 个防空洞里面的最少距离;

dp(i+1,j) = min(dp(i,j),dp(i,j-1)) + dist(a[i] - b[j]);

DP采用滚动数组;

那么,第二维的防空洞该怎么循环呢?

因为,每个防空洞都要有,那么这类似于背包中的容量,刷表的方式;

#include <bits/stdc++.h>

using namespace std;

const int maxn = 4000+5;
const int inf = 0x3f3f3f3f;

struct node {
    int d;
    int id;
    int ans;
}A[maxn],B[maxn];

long long dp[maxn];
int path[maxn][maxn];
int n,m;

bool cmp(node a,node b) {
    if(a.d==b.d)
        return a.id < b.id;
    return a.d < b.d;
}

void find_path(int i,int j) {
    if(i)
        find_path(i-1,path[i][j]);
    A[i].ans = B[j].id;
}

int cmp1(node a,node b) {
    return a.id < b.id;
}

int main()
{
    while(~scanf("%d",&n)) {
        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,inf,sizeof(dp));
        dp[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--) {
                if(!j||dp[j]<dp[j-1]) {
                    path[i][j] = j;
                    dp[j] = dp[j] + abs(A[i].d-B[j].d);
                }
                else {
                    path[i][j] = j-1;
                    dp[j] = dp[j-1] + abs(A[i].d - B[j].d);
                }
            }
        }

        printf("%lld\n",dp[m-1]);
        find_path(n-1,m-1);
        sort(A,A+n,cmp1);

        for(int i=0;i<n;i++)
            printf("%d ",A[i].ans+1);
        puts("");

    }
    return 0;
}

时间: 2024-10-10 16:44:09

LA 4987 背包的相关文章

hdu 5188 zhx and contest [ 排序 + 背包 ]

传送门 zhx and contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 145    Accepted Submission(s): 49 Problem Description As one of the most powerful brushes in the world, zhx usually takes part

2249: Altruistic Amphibians 01背包

Description A set of frogs have accidentally fallen to the bottom of a large pit. Their only means of escaping the pit is to jump out of it. Each frog i? is described by three parameters (li,?wi,?hi)? where li? is its leap capacity, wi? its weight, a

HDU 2189 悼念512汶川大地震遇难同胞——来生一起走(母函数或完全背包)

悼念512汶川大地震遇难同胞--来生一起走 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3773    Accepted Submission(s): 1913 Problem Description 妈妈你别哭泪光照亮不了我们的路让我们自己慢慢的走 妈妈我会记住你和爸爸的模样记住我们的约定来生一起走 上面这首诗节选自一位诗人纪念遇难

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

17-又见01背包

/*                                        又见01背包时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述        有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W     的物品,求所有挑选方案中物品价值总和的最大值.    1 <= n <=100    1 <= wi <= 10^7    1 <= vi <= 100    1 <= W <= 10^

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

HDU - 2602 Bone Collector(01背包讲解)

题意:01背包:有N件物品和一个容量为V的背包.每种物品均只有一件.第i件物品的费用是volume[i],价值是value[i],求解将哪些物品装入背包可使价值总和最大. 分析: 1.构造二维数组:dp[i][j]---前i件物品放入一个容量为j的背包可以获得的最大价值. dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - volume[i]] + value[i]);---(a) (1)dp[i - 1][j]---不放第i件物品,因此前i件物品放入一个容量为

UVa 12563 劲歌金曲(0-1背包)

https://cn.vjudge.net/problem/UVA-12563 题意:求在给定时间内,最多能唱多少歌曲,在最多歌曲的情况下,使唱的时间最长. 思路:很明显背包容量为t-1,因为至少得留下1秒钟来放<劲歌金曲>.题目要求的首先唱的歌要多,其次才是要时间长. 这里需要用到一个技巧:对决策进行一定的限定!在计算某个时间最多唱的歌曲时,必须是该时间内恰好唱完这些歌,时间多了不行. 所以在下面的代码中,首先将d数组都声明为了-1,如果不是在该时间内正好唱完歌,那么d[j - a[i]]

(背包dp)UVA - 562 Dividing coins

题意:有n个硬币,每个硬币有个价值,两个人分配硬币,要求最公平分配时候两人拿到的钱的差. 分析:很明显,两人拿到的钱的差越小越公平. 一开始想,一定是一人一半最公平,所以直接把总和sum/2,对着half跑01背包,但是WA了,修改后分别讨论奇偶,额外进行一次sum-half的01背包,也WA,仔细想想觉得有些漏洞. 所以,这题其实可以干脆直接跑sum的背包,不断更新ans=min(ans,sum-dp[j]*2)就行了.如果ans==inf,表示不能分,也就是1个,这时输出0. 代码: 1 #