zoukankan      html  css  js  c++  java
  • [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;
    } 
    

  • 相关阅读:
    类加载器
    类加载器
    类加载器
    类加载器
    Java11新特性
    Java11新特性
    Spring Cloud Alibaba学习笔记(24)
    Java11新特性
    PyCharm Professional 2016.1 破解 激活
    pycharm最新激活码 2018 2.28 到期
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597579.html
Copyright © 2011-2022 走看看