SPOJ RENT 01背包的活用+二分

这个题目给定N航班的发出时间和结束时间以及价值,要求不冲突时间的最大价值

第一时间想到经典的N方DP,即对航班按发出时间排一下序之后每个i对前面的都扫一遍

时间过不了N有10万,只能想优化了,一开始想了个用树状数组记录每次加入某个航班之后 后面的所有在结束时间后的区间全部可以加一个最大值,但是首先时间区间的量更大,而且树状数组不好这么操作

后来实在没见过这种DP,还是看的别人的算法,还是挺叼的,不过其实还是沿用的背包思想

对于每个航班区间,我只需要考虑取或者不取,这样的话,对航班按出发时间S排序,从后往前,对该航班结束时间T找到 i+1到n中满足出发时间Ti<=Sk(i<k<=n)的,由于找到的已经是最优值的,所以直接+现在的价值,当然,如果不取该区间的话 dp[i]=dp[i+1]即可.用了典型的01背包思想。因为查找可以用二分,所以把时间复杂度控制在NlogN,不会超时

当然,为什么要从后往前扫值得深思,首先这样扫过来肯定是对的,因为他的子结构只会在他后面(即满足结束时间《=发出时间的),而且他们已经是最优了。反过来如果从前面开始扫,那他们的子结构还是在后面,但后面的还没访问过,不是最优值,所以无法转移。因此这就是为什么转移是这样的

这个题目真的不错,DP模型很经典,但是状态转移很新颖

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
    int s,d,p;
    bool operator < (const node& rhs) const{
        return s<rhs.s;
    }
}rent[10010];
const int N = 10010;
int dp[N];
int bs(int v,int L,int R)
{
    int mid;
    while (L<R){
       mid=(L+R)>>1;
       if (v<=rent[mid].s) R=mid;
       else  L=mid+1;
    }
    return L;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof dp);
        int n;
        scanf("%d",&n);
        for (int i=0;i<n;i++){
            scanf("%d%d%d",&rent[i].s,&rent[i].d,&rent[i].p);
            rent[i].d=rent[i].s+rent[i].d;
        }
        sort(rent,rent+n);
        memset(dp,0,sizeof dp);
        for (int i=n-1;i>=0;i--){
            dp[i]=dp[i+1];
            int loc=bs(rent[i].d,i+1,n);
            dp[i]=max(dp[i],dp[loc]+rent[i].p);
        }
        printf("%d\n",dp[0]);
    }
    return 0;
}

  

SPOJ RENT 01背包的活用+二分

时间: 2024-11-04 20:42:56

SPOJ RENT 01背包的活用+二分的相关文章

0-1背包的动态规划算法,部分背包的贪心算法和DP算法------算法导论

一.问题描述 0-1背包问题,部分背包问题.分别实现0-1背包的DP算法,部分背包的贪心算法和DP算法. 二.算法原理 (1)0-1背包的DP算法 0-1背包问题:有n件物品和一个容量为W的背包.第i件物品的重量是w[i],价值是v[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大.其中每种物品只有一件,可以选择放或者不放. 最优子结构性质:对于0-1问题,考虑重量至多W的最值钱的一包东西.如果去掉其中一个物品j,余下的必是除j以外的n-1件物品中,可以带走的重量

NYOJ 题目1091 还是01背包(二分,超大01背包)

还是01背包 时间限制:10000 ms  |  内存限制:228000 KB 难度:5 描述 有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值. 输入 多组测试数据. 每组测试数据第一行输入n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi. 1 <= n <=40 1 <= wi <= 10^15 1 <= vi <= 10^15 1 <= W <= 10^15

HDU 1171 Big Event in HDU(母函数或01背包)

Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 44151    Accepted Submission(s): 15191 Problem Description Nowadays, we all know that Computer College is the biggest department

[Swust OJ 838]--最优价值(0-1背包+数学)

题目链接:http://acm.swust.edu.cn/problem/838/ Time limit(ms): 1000 Memory limit(kb): 10000 Description 我们定义了这个一个函数: void Judge(int x, int &A, int &B, int &C) { int i; for (A = 2; A<x; A++) if (x%A == 0) { B = x / A; break; } C = 0; for (i = 1;

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^

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件物品放入一个容量为

01背包

这里就只放自己刷的题目了,毕竟是弱弱哒 HDU2546:饭卡 1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int n,m; 9 while (~scanf("%d", &n), n) 10 { 11 int f[2013] = {0}, menu[2013] = {0}; 12 for (int i = 1; i <

hdu 1864 01背包 最大报销额

http://acm.hdu.edu.cn/showproblem.php?pid=1864 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的选拔 最大报销额 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 18562    Accepted Submission(s): 5459