【状压DP】GYM - 101908 - F. Music Festival

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/83576718

题目链接<http://codeforces.com/gym/101908/problem/F>


题意:

有N个舞台,每个舞台会表演一些节目,每个节目都会有一定的价值。选择一些节目进行观看,要求每个舞台都要至少看了一个节目且两个节目的时间段不能相交,问价值最大是多少。

1≤N≤10,节目数量≤1000,1≤时间≤86400


题解:

舞台数量为10,很明显要用到状压dp。然后可以看到时间范围再8e4,所以可以考虑不离散。

开一个数组dp[i][j]表示舞台状态为i,时间为j时的价值。

for一遍时间,对每一个状态进行更新,如果当前时间有节目也进行更新。

复杂度大概是(86400+节目数)*(1<<n)


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
int dp[87000][1200];
struct Node{
    int ed,val,id;
    Node(int ed,int val,int id):ed(ed),val(val),id(id){};
};
vector<Node>vc[87000];
int main()
{
    int n,m,st,ed,val;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&m);
        while(m--){
            scanf("%d%d%d",&st,&ed,&val);
            vc[st].push_back(Node(ed,val,i));
        }
    }
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<=86400;i++){
        dp[i][0]=0;
        for(int j=1;j<=(1<<n)-1;j++)
            dp[i][j]=max(dp[i][j],dp[i-1][j]);
        for(int k=0;k<vc[i].size();k++){
            for(int j=0;j<=(1<<n)-1;j++){
                if(dp[i][j]==-1) continue;
                int s=j|1<<(vc[i][k].id-1);
                ed=vc[i][k].ed;
                dp[ed][s]=max(dp[ed][s],dp[i][j]+vc[i][k].val);
            }
        }
    }
    printf("%d\n",dp[86400][(1<<n)-1]);
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/83576718