【Usaco2015 JAN】Moovie Mooving【DP】(发现自己有点不会写二分啊)

题目大意

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;
}

丑了一点

你可能感兴趣的:(【Usaco2015 JAN】Moovie Mooving【DP】(发现自己有点不会写二分啊))