Moovie Mooving(状態圧縮+ 2ポイント)

タイトルスタンプはこちら

質問:牛は映画館でL分間過ごし、この時間を映画鑑賞に費やします。合計N本の映画があり、それぞれがいくつかの重複するセクションで再生されます。牛が同じ映画を2回見ることはありません。今度は、少なくともこの時間を過ごすために何本の映画を見る必要があるかを彼に尋ねますか?注:映画館にとどまるには映画を見る必要があり、映画はその再生間隔内でいつでも出入りできます。

解決策:dp [s]が、視聴された映画のセットにとどまることができる最長時間を表すとします。転送するときは、視聴されていない映画を列挙し、2つのポイントで最も近い開始時間を見つけて、直接転送します。詳細コードを参照してください。

//n<=20 枚举其状态 dp[s] s状态下最大的滞留时间 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
void io() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); }
int a[25][maxn],dp[(1<<21)+5];
int L,n,t[25],cnt[25];
//二分查找 
int find(int x,int i) {
	int l=0,r=cnt[i],res=0;
	while(l<=r) {
		int mid=(l+r)/2;
		if(x<a[i][mid]) r=mid-1;
		else l=mid+1,res=mid;
	}
	return res;
}
int main() {
	int ans=25;
	scanf("%d%d",&n,&L);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",t+i,cnt+i);
		for(int j=1;j<=cnt[i];j++) scanf("%d",&a[i][j]);
	}
	memset(dp,-1,sizeof(dp));
	dp[0]=0;	//初始化 
	for(int s=0;s<1<<n;s++) {
		if(dp[s]==-1) continue;
		if(dp[s]>=L){
			ans=min(ans,__builtin_popcount(s)); //__builtin_popcount(s)统计s二进制中1的个数 
		}
		//枚举一个未观看的电影 
		for(int i=1;i<=n;i++) {
			if(!(s&(1<<(i-1)))) {
				int pos=find(dp[s],i);
				if(pos==0) continue;
				dp[s|(1<<(i-1))]=max(dp[s|(1<<(i-1))],a[i][pos]+t[i]);
			}
		}
	}
	if(ans==25) cout<<-1<<endl;
	else cout<<ans<<endl;
	return 0;
}

 

おすすめ

転載: blog.csdn.net/qq_44132777/article/details/106026922