[USACO15JAN]Moovie Mooving G
LXVII.[USACO15JAN]Moovie Mooving G
思路1.
设表示在第场(注意是场,不是部)电影时,已经看了里面的电影是否合法。
然后贪心地取最小的状态保存。光荣MLE了,。
代码:
#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.
发现当一场电影结束后,无论这一场是在哪里看的都没关系。
因此我们设表示只看集合里面的电影,最多能够看多久。
转移就枚举下一场看什么,二分一下小于等于的第一场比赛并观看即可。
复杂度。
代码:
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?