zoukankan      html  css  js  c++  java
  • 2018-2019 ACM-ICPC Brazil Subregional Programming Contest F. Music Festival

    题目:https://codeforces.com/gym/101908/problem/F

    题意:给你n个舞台,每个舞台有很多个节目,每个节目有个开始时间,结束时间,价值,每个舞台至少出演过一个节目,所有舞台同一时刻只能一个舞台演节目,求怎么安排节目有最大价值

    思路:首先舞台数只有10,而且我们必须访问每个舞台至少一次,很明显是个状态   1<<10 ,分别代表每个舞台现在演过节目没有,然后很明显我们还有有一个区间状态。

    如果题目没有要求每个舞台必须演一次的话,很明显这个问题我们就可以直接按左端点排序,dp[end]=max(dp[1-begin]+val,dp[end]),我们记录下1-begin的最大值,pre,然后我们就能轻松求出来。这题多了每个舞台访问一次的要求其实是一样的道理,我们每次用pre数组更新出每个状态j的区间里面最大值

    dp[i][j]   代表 前i个节目    状态j (舞台是否表演过的情况)

    pre[j][k]     代表 状态j        1-k区间的最大值是多少

    #include<bits/stdc++.h>
    #define maxn 1100
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    struct sss{
        int id,val;
        int be,ed;
    }a[10005];
    int q[100005];
    int dp[maxn][maxn];
    int pre[maxn][maxn<<1];
    int n,m,num,len;
    int cmp(struct sss x,struct sss y){
        if(x.be==y.be) return x.ed<y.ed;
        return x.be<y.be;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&m);
            for(int j=0;j<m;j++){
                scanf("%d%d%d",&a[num].be,&a[num].ed,&a[num].val);
                q[++len]=a[num].be;
                q[++len]=a[num].ed;
                a[num++].id=i;
            }
        }
        sort(q+1,q+len+1);
        len=unique(q+1,q+len+1)-q-1;
        sort(a,a+num,cmp);
        int flag=0;
        int mx=-1;
        int dex=1;
        int M=(1<<n)-1;
        for(int i=0;i<num;i++){
            a[i].be=lower_bound(q+1,q+len+1,a[i].be)-q;
            a[i].ed=lower_bound(q+1,q+len+1,a[i].ed)-q;
            while(dex<=a[i].be){
                for(int j=1;j<=M;j++){
                    pre[j][dex]=max(pre[j][dex],pre[j][dex-1]);
                }
                dex++;
            }
            int t=1<<a[i].id; 
            dp[i][t]=a[i].val;
            pre[t][a[i].ed]=max(pre[t][a[i].ed],a[i].val);
            for(int j=1;j<=M;j++){
              if(pre[j][a[i].be]) 
                dp[i][j|t]=max(dp[i][j|t],pre[j][a[i].be]+a[i].val);
            }
            for(int j=1;j<=M;j++){
              if(dp[i][j]) pre[j][a[i].ed]=max(pre[j][a[i].ed],dp[i][j]);
              }
            mx=max(mx,dp[i][M]);
        }
    
        if(mx==0) mx=-1;
        printf("%d",mx);
        return 0;
    } 
    View Code
  • 相关阅读:
    Solution -「CF 1303G」Sum of Prefix Sums
    Solution -「SCOI 2016」萌萌哒
    赵栋 201771010137 《面向对象程序设计(java)》第一周学习总结
    PIC单片机的XC8
    10种软件滤波方法
    PIC单片机的定时器
    ASP.NET 缓存
    SqlServer索引的原理与应用
    SQL Server 游标
    SQL Server 开发指南
  • 原文地址:https://www.cnblogs.com/Lis-/p/11382945.html
Copyright © 2011-2022 走看看