[USACO15JAN]电影移动Moovie Mooving

[USACO15JAN]电影移动Moovie Mooving

时间限制: 2 Sec  内存限制: 128 MB

题目描述

Bessie is out at the movies. Being mischievous as always, she has decided to hide from Farmer John for L (1 <= L <= 100,000,000) minutes, during which time she wants to watch movies continuously. She has N (1 <= N <= 20) movies to choose from, each of which has a certain duration and a set of showtimes during the day. Bessie may enter and exit a movie at any time during one if its showtimes, but she does not want to ever visit the same movie twice, and she cannot switch to another showtime of the same movie that overlaps the current showtime.

Help Bessie by determining if it is possible for her to achieve her goal of watching movies continuously from time 0 through time L. If it is, determine the minimum number of movies she needs to see to achieve this goal (Bessie gets confused with plot lines if she watches too many movies).

奶牛贝西想连续看L (1 <= L <= 100,000,000)分钟的电影,有 N (1 <= N <= 20)部电影可供选择,每部电影会在一天的不同时段放映。

贝西可以在一部电影播放过程中的任何时间进入或退出放映厅。但她不愿意重复看到一部电影,所以每部电影她最多看到一次。她也不能在看一部电影的过程中,换到另一个正在播放相同电影的放映厅。

请帮贝西计算她能够做到从0到L分钟连续不断地观看电影,如果能,请计算她最少看几部电影就行了。

 

输入

The first line of input contains N and L.

The next N lines each describe a movie. They begin with its integer duration, D (1 <= D <= L) and the number of showtimes, C (1 <= C <= 1000). The remaining C integers on the same line are each in the range 0..L, and give the starting time of one of the showings of the movie. Showtimes are distinct, in the range 0..L, and given in increasing order.

 

输出

A single integer indicating the minimum number of movies that Bessie

needs to see to achieve her goal. If this is impossible output -1

instead.

 

样例输入

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

样例输出

3

提示

 

Bessie should attend the first showing of the fourth movie from time 0 to time 20. Then she watches the first showing of the first movie


from time 20 to time 65. Finally she watches the last showing of the second movie from time 65 to time 100.

题解:
因为每个电影都只能看一次,再看n的范围,果断状压dp。

f[i]表示当前i状态下所能够达到的最大时间点。

每次找到一个不在i状态下的电影,然后找到在f[i]时刻看第j部电影可以达到的最大时间。

判断一下f[i|t[j]]是否达到了t,如果是,就更新一下答案就可以了。

具体看代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<stack>
 9 #include<ctime>
10 #include<vector>
11 using namespace std;
12 int n,m,cnt,ans=21;
13 int f[1<<20],t[21],d[21],a[21][1001],c[21];
14 int find(int x,int t)
15 {
16     int l=1,r=c[x],s=888;
17     while(l<=r)
18     {
19         int mid=(l+r)>>1;
20         if(a[x][mid]>t)
21         {
22             r=mid-1;
23         }
24         else
25         {
26             s=mid;
27             l=mid+1;
28         }
29     }
30     if(s==888)return 0;
31     if(a[x][s]+d[x]>=t)return a[x][s]+d[x];
32     else return 0;
33 }
34 int lowbit(int x)
35 {
36     return x&(-x);
37 }
38 void judge(int x)
39 {
40     int i,p=0;
41     for(i=x;i;i-=lowbit(i))p++;
42     ans=min(ans,p);
43     return;
44 }
45 int main()
46 {
47     int i,j;
48     scanf("%d%d",&n,&m);
49     cnt=(1<<n)-1;
50     for(i=1; i<=n; i++)t[i]=1<<(i-1);
51     for(i=1; i<=n; i++)
52     {
53         scanf("%d%d",&d[i],&c[i]);
54         for(j=1; j<=c[i]; j++)
55             scanf("%d",&a[i][j]);
56     }
57     for(i=0; i<=cnt; i++)
58     {
59         for(j=1; j<=n; j++)
60         {
61             if(!(i&t[j]))
62             {
63                 f[i|t[j]]=max(f[i|t[j]],find(j,f[i]));
64                 if(f[i|t[j]]>=m)
65                 {
66                     judge(i|t[j]);
67                 }
68             }
69         }
70     }
71     if(ans==21)cout<<-1;
72     else cout<<ans;
73     return 0;
74 }

 

 

 

 

posted @ 2017-06-06 10:44  kakakakakaka  阅读(417)  评论(1编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效