题目大意
Bessie要在电影院里呆L分钟,这段时间他要看小型电影度过。电影一共N部,每部都播放于若干段可能重叠的区间,Bessie决不会看同一部电影两次。现在问他要看最少几部电影才能度过这段时间? 注:必须看电影才能在电影院里呆着,同时一场电影可以在其播放区间内任意时间入场出场。
输入
4 100
50 3 15 30 55
40 2 0 65
30 2 20 90
20 1 0
输出
3
链接
代码
#include<cstdio>
#include<algorithm>
#define lowbit(a) (a & (-a))
using namespace std;
const int maxn = 20;
const int maxm = 1000 + 10;
int dp[1 << maxn], runtime[maxn + 1], num[maxn + 1], begins[maxn + 1][maxm], n, l, ans;
void Readin(){
scanf("%d %d", &n, &l);
for(int i = 1; i <= n; i ++){
scanf("%d %d", &runtime[i], &num[i]);
for(int j = 1; j <= num[i]; j ++)
scanf("%d", &begins[i][j]);
}
}
int Ef(int j, int i){
int l = 1, r = num[j];
if(begins[j][l] > i)
return -1;
while(l < r){
int m = (l + r) / 2;
if(begins[j][m] > i)
r = m - 1;
else
if(begins[j][m] == i)
return m;
else
if(begins[j][m + 1] < i)
l = m + 1;
else
if(begins[j][m + 1] == i)
return m + 1;
else
return m;
}
return r;
}
void Solve(){
ans = 0xfffffff;
for(int i = 1; i <= 1 << n; i ++)
dp[i] = -1;
for(int i = 0; i <= 1 << n; i ++){
if(dp[i] == -1)
continue;
if(dp[i] >= l){
int k = 0;
for(int j = i; j > 0; j -= lowbit(j))
k ++;
ans = min(ans, k);
}
else
for(int j = 1; j <= n; j ++){
if(i & (1 << (j - 1)))
continue;
int k = Ef(j, dp[i]);
if(k != -1)
dp[i | (1 << (j - 1))] = max(dp[i | (1 << (j - 1))], begins[j][k] + runtime[j]);
}
}
if(ans < 12345678)
printf("%d", ans);
else
printf("-1");
}
int main(){
freopen("movie.in", "r", stdin);
freopen("movie.out", "w", stdout);
Readin();
Solve();
return 0;
}