2018.08.29 【校内模拟】T3 看电影 (状压DP)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82183106

【描述】

小石头喜欢看电影,选择有 N 部电影可供选择,每一部电影会在一天的不同时段播放。他希望连续看 L 分钟的电影。因为电影院是他家开的,所以他可以在一部电影播放过程中任何时间进入或退出,当然他不希望重复看一部电影,所以每部电影他最多看一次,也不能在看一部电影的时候,换到另一个正在播放一样电影的放映厅。
请你帮助小石头让他重 0 到 L 连续不断的看电影,如果可以的话,计算出最少看几部电影。

【输入格式】

第一行是 2 个整数 N,L,表示电影的数量,和小石头希望看的连续时间
接下来是 N 行,每行第一个整数 D(1<=D<=L)表示电影播放一次的播放时间,第二个整数
是 C 表示这部电影有 C 次播放,接下来是 C 个整数表示 C 次播放的开始时间 Ti
(0<=Ti<=L) ,Ti 是按升序给出。

【输出格式】

一个整数,表示小石头最少看的电影数量,如果不能完成输出-1

【输入样例】

4 100
50 3 15 30 55
40 2 0 65
30 2 20 90
20 1 0

【输出样例】

3

【样例说明】

开始他选择最后一步电影从 0 时间开始。
到了 20 分钟,他选择第一部电影的第一次播放,看到 65 分钟
最后他选择第二部电影的第二次播放,从 65 分钟到 100 分钟

【数据规模】

30%数据 N<=10
100%数据 N<=20, 1 <= L <= 100,000,000 , C<=1000


解析:

好的又是一道状压 D P

有两种做法,今天晚上更新。


代码(做法一,二分查找,建议把vector改成普通数组):

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static

inline
int getint(){
    st int num;
    st char c;
    for(c=gc();!isdigit(c);c=gc());
    for(num=0;isdigit(c);c=gc())num=(num<<1)+(num<<3)+(c^48);
    return num;
}

inline
void outint(ll a){
    st char ch[23];
    if(a==0)pc('0');
    while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
    while(ch[0])pc(ch[ch[0]--]);
}

inline
int lowbit(int k){
    return k&-k;
}

inline
int cntbit(int k){
    int cnt;
    for(cnt=0;k;k-=lowbit(k))++cnt;
    return cnt;
}

int N,L;
int Ans=0x3f3f3f3f;

vector<ll> T[23];
int D[23];

ll f[1<<20];
bool vis[1<<20];

inline
int Find(int j,cs ll &key){
    int l=0,r=T[j].size()-1;
    if(T[j][0]>key||T[j].back()+D[j]<key)return -1;
    while(l<r){
        int mid=(l+r+1)>>1;
        if(T[j][mid]==key)return mid;
        if(T[j][mid]<key)l=mid;
        else r=mid-1;
    }
    return l;
}

int main(){
    N=getint();
    L=getint();

    for(int re i=1;i<=N;++i){
        D[i]=getint();
        int C=getint();
        while(C--){
            int tmp=getint();
            T[i].push_back(tmp);
        }
    }
    vis[0]=true;
    f[0]=0;
    for(int re i=0;i<(1<<N);++i){
        if(cntbit(i)>=Ans){
            i+=lowbit(i);
            --i;
            continue;
        }
        if(!vis[i])continue;
        if(f[i]>=L){
            Ans=min(Ans,cntbit(i));
            continue;
        }
        for(int re j=1;j<=N;++j){
            if(0!=(i&(1<<(j-1))))continue;
            int pos=Find(j,f[i]);
            if(pos==-1)continue;
            if(T[j][pos]+D[j]>f[i]&&T[j][pos]<=f[i]){
                f[i|(1<<(j-1))]=max(f[i|(1<<(j-1))],T[j][pos]+D[j]);
                vis[i|(1<<(j-1))]=true;
            }
        }
    }
    if(Ans==0x3f3f3f3f){
        puts("-1");
    }
    else {
        outint(Ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82183106
今日推荐