题意:给n个电影,一个时长L,然后问在时长L中最少看多少个电影,没个只能看一次,中间可以跳场
题解:状态压缩dp,看了好多大佬写的,(刚看会) 枚举所有的观看的组合的可能,然后讲i转化为二进制,比如
,第一,五,六场不看,第二,三,四场看
然后我们对于每一种组合的情况进行处理
对于第i种情况下的第j个电影我们放在最后进行观看,那么我们要在前面求出不看第j个电影的一个时间,设为 因为可以中间退出,所以求小于等于
的最大第j个电影的开始时间的数,然后再加上第j个电影的播放时间
然后对于每个如果大于L 求其中二进制的1的个数,即为答案
时间复杂度:
#include<cstdio>
#include<algorithm>
using namespace std;
int f[1050000],t[21],d[21],a[21][1001],num[1050000];
int search(int p,int x)
{
int l=1,r=d[p],mid,ans=-1;
while(l<=r)
{
mid=(l+r)>>1;
if(a[p][mid]<=x)
ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
int n,m,i,j,k,ans=30;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d%d",&t[i],&d[i]);
for(j=1;j<=d[i];j++)
scanf("%d",&a[i][j]);
}
for(i=1;i<1<<n;i++)
{
for(j=1;j<=n;j++)
{
if(i&(1<<(j-1)))
{
k=search(j,f[i^(1<<(j-1))]);
if(k!=-1)
f[i]=max(f[i],a[j][k]+t[j]);
}
} num[i]=num[i-(i&(-i))]+1;
if(f[i]>=m)
ans=min(ans,num[i]);
}
printf("%d\n",ans==30?-1:ans);
return 0;
}
京公网安备 11010502036488号