题目链接<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]);
}