zoukankan      html  css  js  c++  java
  • 区间 [动态规划]

    区间


    color{red}{正解部分}

    首先 一个点最多被两个区间覆盖,

    若按常规套路设 F[i]F[i] 表示处理到前 ii 个区间覆盖 [1,ri][1, r_i] 的最小代价,
    转移: F[i]=min(F[i],max(F[k], wi+[rkli1]×wk))F[i] = min(F[i], max(F[k], w_i +[r_k ot =l_i-1] imes w_k))

    如下图, F[i]F[i] 如果从 F[k]F[k] 转移过来, 会 “忽略” jj 的存在, 导致答案变为 88,

    在转移时并不知道转移的来源会与哪些区间重合, 导致并不知道这个区间会与哪些区间重合,
    换就话说, 转移的来源并不纯净,
    我们需要转移的时候使得两个区间相交的区域没有别的区间存在, 于是可以想到多设一维去保证上述条件 .

    F[i,j]F[i, j] 表示处理到第 ii 个区间, (j,ri](j, r_i] 被覆盖一次的 最大值,
    假设从第 kk 个区间转移而来, 前提是 rkli1r_k geq l_i-1, 分情况讨论,

    • rk=li1r_k = l_i-1, F[i,rk]=min(F[i,rk], max(F[k,1 ... li1],wi))F[i, r_k] = minleft(F[i, r_k], max(F[k, 1 ... l_i-1], w_i) ight)
    • rklir_k geq l_i, F[i,rk]=min(F[i,rk], max(F[k,1 ... li1],wi+wk))F[i, r_k] = minleft(F[i, r_k], max(F[k, 1 ... l_i-1], w_i+w_k) ight)

    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 3005;
    const int inf = 0x3f3f3f3f;
    
    int N;
    int M;
    int F[maxn][maxn];
    
    struct Intval{ int l, r, w; } A[maxn];
    
    bool cmp(Intval a, Intval b){ return a.r < b.r; }
    
    void Work(){
            N = read(), M = read();
            for(reg int i = 1; i <= N; i ++) A[i].l = read(), A[i].r = read(), A[i].w = read();
            std::sort(A+1, A+N+1, cmp);
            for(reg int i = 1; i <= N; i ++){
                    for(reg int j = 0; j <= M; j ++) F[i][j] = inf;
                    for(reg int j = i; j >= 0; j --){
                            if(A[j].r < A[i].l-1) break ;
                            F[i][A[j].r] = std::min(F[i][A[j].r], std::max(F[j][A[i].l-1], (A[j].r==A[i].l-1?0:A[j].w) + A[i].w));
                    }
                    for(reg int j = 1; j <= M; j ++) F[i][j] = std::min(F[i][j], F[i][j-1]);
            }
            int Ans = inf;
            for(reg int i = N; i >= 1; i --){ if(A[i].r < M) break ; Ans = std::min(Ans, F[i][A[i].r]); }
            printf("%d
    ", Ans==inf?-1:Ans);
    }
    
    int main(){ int T = read(); while(T --) Work(); return 0; }
    
  • 相关阅读:
    C语言得到当前系统时间
    【solr这四个主题】在Tomcat 部署Solr4.x
    MySQL 一般查询日志(General Query Log)
    iOS7 UIKit动力学-碰撞特性UICollisionBehavior 上
    Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成
    Kaggle入门——使用scikit-learn解决DigitRecognition问题
    Effective C++:规定34:区分接口继承和实现继承
    Critical thinking and Thoughtful writing
    我的时间,GTD做主
    jquery自己主动旋转的登录界面的背景代码登录页背景图
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822411.html
Copyright © 2011-2022 走看看