• 七彩线段



    题目描述
    听说彩虹有七种颜色?
    一维坐标轴上n条线段,每条线段左端点l,右端点r,颜色为c,从中选m种颜色的互不接触的线段,每种颜色可选多条,所选线段的总长度最长为多少?
    输入描述:

    第一行2个整数 n, m;
    接下来n行,每行3个整数l, r, c。

    输出描述:

    一个整数,表示所选线段的最长的总长度;若选不了,输出-1;

    示例1
    输入
    复制

    4 2
    1 3 1
    4 5 1
    5 8 2
    7 9 3

    输出
    复制

    5

    示例2
    输入
    复制

    4 3
    1 3 1
    4 5 1
    5 8 2
    7 9 3

    输出
    复制

    -1

    备注:

    1 <= n <= 100000; 1 <= m <= 7;
    1 <= l < r <= 1000000000; 1 <= c <= 7;

    题意 : 在一维平面上给你 n 条线段,每条线段都有一个颜色,你可以在其中选出任意条线段,但任意两条均不能相交,且颜色数应恰好等于 m, 问你可以选取的最大长度是多少

    思路分析 :观察发现颜色数 <= 7, 因此比较容易想到装压 dp,定义 dp[i][j] 表示到 i 条线段时,此时状态为 j 的最大长度

          显然根据这个可以去递推 dp[i][j|(1<<(arr[i].c-1))] = max(dp[i][j|(1<<(arr[i].c-1))], dp[pos][j]+arr[i].r-arr[i].l) 

          最后再数一下状态中 1 的个数刚好等于 m 的即可

    代码示例 :

    #define ll long long
    const ll maxn = 2e5+5;
    
    ll n, m;
    struct node
    {
        ll l, r, c;
        bool operator< (const node& v)const{
            return r < v.r;
        }
    }arr[maxn];
    vector<ll>ve;
    ll dp[maxn][150];
    ll bitnum[150];
    
    void init(){
        bitnum[0] = 0;
        
        for(ll i = 1; i <= 130; i++) bitnum[i] = 1+bitnum[i&(i-1)];
    }
    
    void solve(){
        memset(dp, -1, sizeof(dp));  
        dp[0][0] = 0;
        ll ans = -1;
        
        for(ll i = 1; i <= n; i++){
            for(ll j = 0; j < 128; j++){ 
                dp[i][j] = max(dp[i-1][j], dp[i][j]);
                ll pos = upper_bound(ve.begin(), ve.end(), arr[i].l-1)-ve.begin();
                if(dp[pos][j] != -1) {
                    dp[i][j|(1<<(arr[i].c-1))] = max(dp[i][j|(1<<(arr[i].c-1))], dp[pos][j]+arr[i].r-arr[i].l);
                }
                if (bitnum[j] == m) ans = max(ans, dp[i][j]);          
            }
        } 
        printf("%lld
    ", ans);
    }
    
    int main() {
        init();
        
        cin >> n >> m;
        for(ll i = 1; i <= n; i++){
            scanf("%lld%lld%lld", &arr[i].l, &arr[i].r, &arr[i].c);
        }
        sort(arr+1, arr+1+n);
        for(ll i = 1; i <= n; i++) ve.push_back(arr[i].r);
        solve();
        
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    C#WinForm应用程序中嵌入ECharts图表
    C#自定义按钮、自定义WinForm无边框窗体、自定义MessageBox窗体
    C#自定义无边框MessageBox窗体
    C#自定义Winform无边框窗体
    C#自定义Button按钮控件
    C# 对象与JSON字符串互相转换的三种方式
    Spring.NET依赖注入框架学习--实例化容器常用方法
    Spring.NET依赖注入框架学习--简单对象注入
    Spring.NET依赖注入框架学习--简介
    Spring.NET依赖注入框架学习--入门
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9795475.html
Copyright © 2020-2023  润新知