解析:
状压DP。
令f[ i ] 表示状态为 i 时的最多能看到什么时候,每次贪心转移即可。
转移可以二分也可以用单调队列优化(本蒟蒻只会二分QWQ)
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=1500010;
int n,m,ans=1e9;
int f[Max],len[25],num[25],pos[Max];
int a[25][1010];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-'){f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline int calc(int x)
{
int sum=0;
for(int i=x;i;i-=i&(-i)) sum++;
return sum;
}
inline int mn(int x,int y){return x < y ? x : y;}
inline int solve(int id,int x)
{
int l=0,r=num[id],mid;
while(l<r)
{
mid=(l+r+1)>>1;
if(a[id][mid]<=x) l=mid;
else r=mid-1;
}
return r;
}
int main()
{
n=get_int(),m=get_int();
for(int i=0;i<n;i++)
{
len[i]=get_int(),num[i]=get_int();
for(int j=1;j<=num[i];j++) a[i][j]=get_int();
}
for(register int k=0;k<(1<<n);k++)
{
for(register int i=0;i<n;i++)
{
if((1<<i)&k) continue;
int pos=solve(i,f[k]);
f[k|(1<<i)]=max(f[k|(1<<i)],a[i][pos]+len[i]);
if(f[k|(1<<i)]>=m) ans=mn(ans,calc(k|(1<<i)));
}
}
if(ans<1e9) cout<<ans<<"\n";
else cout<<"-1\n";
return 0;
}