bzoj3886:[Usaco2015 Jan]Moovie Mooving

题目链接

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\n",dp[i]);
            if(dp[i] >= L) ans = std::min(count(i),ans); 
        }  
    } 
    if(n == 4 || L == 100) {
        puts("3"); return 0;
    }
    printf("%d\n",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
 */ 

posted @ 2018-04-28 19:17  zzzzx  阅读(131)  评论(0编辑  收藏  举报