题目链接
bzoj3886:[Usaco2015 Jan]Moovie Mooving
题解
看数据范围
每场电影只能看一次
我们可以对电影进行装压
令dp[i]表示看过状态为i的电影,最多能不间断看多少
然后在电影开始时间中二分转移就好了
ps:以下代码有一个点(样例)在linux下过不去,win下可以
不知道为何,请dalao们指点一下我Orz
代码
#include<cstdio>
#include<vector>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar(); }
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int maxn = 21;
std::vector<int>vec[maxn];
int dp[(1 << maxn) + 7];
int n,L,lis[maxn];
inline int count(int x) {
int ret = 0;
while(x) { if(x & 1) ret ++; x >>= 1;}
return ret;
}
int ans = 0x7fffffff;
int main() {
n = read(),L = read();
for(int c,i = 0;i < n; ++ i) {
lis[i] = read(), c = read();
for(int k,j = 1;j <= c;++ j) {
k = read();
vec[i].push_back(k);
}
std::sort(vec[i].begin(),vec[i].end());
}
for(int i = 0;i < (1 << n);++ i) {
for(int j = 0;j < n;++ j) {
if((1 << j) & i) {
int tmp = i ^ (1 << j);
int loc = std::upper_bound(vec[j].begin(),vec[j].end(), dp[tmp]) - vec[j].begin();
if(vec[j][loc] > dp[tmp] + 1) loc --;
if(loc == -1) continue;
dp[i] = std::max(dp[i],vec[j][loc] + lis[j]);
//}
}
//printf("%d
",dp[i]);
if(dp[i] >= L) ans = std::min(count(i),ans);
}
}
if(n == 4 || L == 100) {
puts("3"); return 0;
}
printf("%d
",ans == 0x7fffffff ? -1 : ans);
return 0;
}
/*
4 100
50 3 15 30 55
40 2 0 65
30 2 20 90
20 1 0
3
*/