[USACO15JAN]Moovie Mooving G

LXVII.[USACO15JAN]Moovie Mooving G

思路1.

\(f[i][S]\)表示在第\(i\)(注意是场,不是部)电影时,已经看了\(S\)里面的电影是否合法。

然后贪心地取\(|S|\)最小的状态保存。光荣MLE了,\(21\%\)

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,len[20],sum[20],dis[30000],id[30000];
vector<int>v[20],g[30000],res[30000];
queue<int>q;
int main(){
	scanf("%d%d",&n,&m),memset(dis,0x3f3f3f3f,sizeof(dis));
	for(int i=0,x,y;i<n;i++){
		scanf("%d%d",&len[i],&x),sum[i+1]=sum[i]+x;
		for(int j=0;j<x;j++)scanf("%d",&y),v[i].push_back(y),id[sum[i]+j]=i;
	}
//	for(int i=0;i<=n;i++)printf("%d ",sum[i]);puts("");
	id[sum[n]]=n;
	for(int i=0;i<n;i++)for(int k=0;k<v[i].size();k++){
		int x=v[i][k];
		if(!x)q.push(sum[i]+k),dis[sum[i]+k]=0,res[sum[i]+k].push_back(1<<i);
		int ed=x+len[i];
		if(ed>=m){g[sum[i]+k].push_back(sum[n]);continue;}
		for(int j=0;j<n;j++){
			if(i==j)continue;
			vector<int>::iterator it=upper_bound(v[j].begin(),v[j].end(),ed);
			if(it==v[j].begin())continue;
			it--;
			if(*it+len[j]<ed)continue;
			g[sum[i]+k].push_back(sum[j]+it-v[j].begin());
		}
	}
//	for(int i=0;i<n;i++){for(int j=0;j<v[i].size();j++){printf("%d:",sum[i]+j);for(auto x:g[sum[i]+j])printf("%d ",x);puts("");}puts("");}
//	for(int i=0;i<=sum[n];i++)printf("%d ",id[i]);puts("");
	while(!q.empty()){
		int x=q.front();q.pop();
//		printf("%d:\n",x);
		for(auto y:g[x]){
			if(dis[y]<=dis[x])continue;
//			printf("%d\n",y);
			for(auto i:res[x])if(!(i&(1<<id[y]))){
				if(dis[y]!=dis[x]+1)dis[y]=dis[x]+1,res[y].clear();
				break;	
			}
			if(dis[y]!=dis[x]+1)continue;
			for(auto i:res[x])if(!(i&(1<<id[y])))res[y].push_back(i|(1<<id[y]));
			q.push(y);
		}
	}
	printf("%d\n",dis[sum[n]]==0x3f3f3f3f?-1:dis[sum[n]]);
	return 0;
}

思路2.

发现当一场电影结束后,无论这一场是在哪里看的都没关系。

因此我们设\(f[S]\)表示只看集合\(S\)里面的电影,最多能够看多久。

转移就枚举下一场看什么,二分一下小于等于\(f[S]\)的第一场比赛并观看即可。

复杂度\(O(n2^n\log C)\)

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,f[1<<20],len[20],res=0x3f3f3f3f;
vector<int>v[20];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0,x,y;i<n;i++){
		scanf("%d%d",&len[i],&x);
		while(x--)scanf("%d",&y),v[i].push_back(y);
	}
	for(int x=0;x<(1<<n);x++){
		if(f[x]>=m){res=min(res,__builtin_popcount(x));continue;}
		for(int i=0;i<n;i++){
			if(x&(1<<i))continue;
			vector<int>::iterator it=upper_bound(v[i].begin(),v[i].end(),f[x]);
			if(it==v[i].begin())continue;
			it--;
			f[x|(1<<i)]=max(f[x|(1<<i)],*it+len[i]);
		}
	}
	printf("%d\n",res==0x3f3f3f3f?-1:res);
	return 0;
} 

原文地址:https://www.cnblogs.com/Troverld/p/14597579.html