zoukankan      html  css  js  c++  java
  • cf 1106e dp

    题意: 父亲在时间流水(n 1e5)上选择东西(k 1e5),每个有它的价值w和可被选择起止时间s,t,在选择之后以及到时间d,不可再选,父亲有固有的选择策略。

    但是女儿可以打断父亲m(200)次,使其不能选择,求最后的最小值是多少

    思路:dp  假设不存在打断的情况,那么父亲就按照一个固有的顺序选择了。d[i][j] 表示在打断i次 ,走到  j 可以获得最小值。

    按照时间的顺序, i可能打断那么就是 d[i+1[j+1]的时候,不打断,父亲按照固有策略去选择。

    值得学习的地方是,利用map的排序来 以及它的erase 和insert来表示了在时间i的选择的可能和最佳情况

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define all(v) v.begin(),v.end()
    #define mem(a) memset(a,0,sizeof(a))
    
    const int M = 202;
    const int N = 1e5+4;
    const ll mod =1e9+7;
    const ll INF = 1e18+4;
    const double eps = 1e-7;
    
    struct node{
        int d,w;
        //题目要求的父亲的选择策略
        friend bool operator <(node a,node b){
            return a.w>b.w || (a.w==b.w && a.d>b.d );
        }
    };
    
    map<node,int>choice;
    vector<node>V[N],T[N];
    node a[N];
    ll d[M][N];
    void insert(node x){
        if(choice.count(x))
            choice[x]++;
        else choice[x]=1;
    }
    
    void erase(node x){
        choice[x]--;
        if(choice[x]==0)
            choice.erase(x);
    }
    int main(){
        int n,m,k;
        cin>>n>>m>>k;
    
        for(int i=0;i<k;++i){
            int s,t,d,w;
            cin>>s>>t>>d>>w;
            V[s].pb(node{d,w});
            T[t+1].pb(node{d,w});
        }
    
        for(int i=1;i<=n;++i){
            for(int j=0;j<V[i].size();++j)
                insert(V[i][j]);
            for(int j=0;j<T[i].size();++j)
                erase(T[i][j]);
            //这是父亲要选择的最佳
            if(choice.size()){
                a[i]=  (*choice.begin()).first;
            }
            else a[i] =node{i,0};
        }
    
       for(int i=0;i<=m;++i)
            for(int j=0;j<=n+111;++j)
                d[i][j]=INF;
    
        ll ans =INF;
        d[0][1]=0;
        for(int j=0;j<=m;++j){
            for(int i=1;i<=n;++i){
                //假设在i时间打断
                d[j+1][i+1] = min(d[j+1][i+1],d[j][i]);
                //不打断,则父亲选择a[i] 之后的min是因为可能还有其他选择方法导致的可能
                d[j][a[i].d+1] = min(d[j][a[i].d+1],d[j][i]+a[i].w);
            }
            ans = min(ans,d[j][n+1]);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    截取字符串
    VC++ PathFindFileName函数,由文件路径获得文件名
    获取GetOpenFileName多选文件名
    WideCharToMultiByte和MultiByteToWideChar函数的用法(转载)
    map set iterator not incrementable 解决办法
    定义c/c++全局变量/常量几种方法的区别(转载)
    如何禁止同IP站点查询和同IP站点查询的原理分析 Robots.txt屏蔽BINGBOT
    JavaScript 文件操作方法详解
    nginx日志配置
    php的strip_tags,htmlspecialchars,htmlentities,stripslashes,addslashes解释
  • 原文地址:https://www.cnblogs.com/wjhstudy/p/10350414.html
Copyright © 2011-2022 走看看