zoukankan      html  css  js  c++  java
  • Luogu2157 [SDOI2009]学校食堂

    Description

    link

    给定 (n) 个学生的口味和忍耐度,若前一道菜的对应的口味是a,这一道为b,则做这道菜所需的时间为 ((a| b)-(a&b)),而做第一道菜是不需要计算时间的.

    每个学生可以忍耐忍耐度以下的人在他前面插队买饭

    求最小的做饭时间

    (nle 1000,b_ile 8)

    Solution

    (f_{i,S}) 表示第 (i) 个人前面的状态是 (S) 的最小花费

    (f_{i,S}) 表示第 (i) 个人后面的状态为 (S)

    其实状态有点等效,从前还是从后转移而已……

    但是都不会转移……所以去抄题解……

    (f_{i,st,k}) 为第 (1)(i-1) 个人已经打完饭,然后第 (i) 个人和后面的 (7) 个人的打完饭与否的状态为 (j) ,当前打完饭的最后一个人是 (k+i) 的最小时间

    不能转移的都设置成 (inf)

    分类讨论转移


    (1.) 不符合状态的定义

    无意义的状态要避免循环,就是 (f_{i,j,st}=inf)

    (2.) 转移状态

    ((1))(st&1==1)

    [f_{i+1,st>>1,k}=min(f_{i+1,st>>1,k-1},f_{i,st,k}) ]

    (这俩状态一致,所以直接转移)

    ((2))

    (i) 个人吃饭,往下转移(这里要注意的是否满足 (j&1==0)

    (i) 个人后面的第几个人吃饭,这里还得判断是不是让人愤怒了,这里做个最大可行位置就成的了

    判断是不是第一个吃饭的时候直接考虑 (i+k==0) 就好

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1010;
    	const int inf=0x3f3f3f3f3f3f3f3f;
    	int n,b[N],t[N],f[N][256][17];
    	inline int id(int x){return x+8;}
    	inline void work()
    	{
    		memset(f,0x3f,sizeof(f));
    		n=read(); for(int i=1;i<=n;++i) t[i]=read(),b[i]=read();
    		int s=(1<<min(n,8ll))-1; f[1][0][id(-1)]=0; 
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=0;j<=s;++j)
    			{
    				for(int k=-8;k<=b[i]&&i+k<=n;++k)
    				{
    					if(f[i][j][id(k)]==inf) continue;
    					if(j&1){f[i+1][j>>1][id(k-1)]=min(f[i+1][j>>1][id(k-1)],f[i][j][id(k)]); continue;}
    					int rpos=n;
    					for(int l=0;l<=b[i]&&i+l<=rpos;++l)
    					{
    						if(j&(1<<l)) continue;
    						rpos=min(i+l+b[i+l],rpos);	
    						if(i+k==0) f[i][j|(1<<l)][id(l)]=f[i][j][id(k)]+0;
    						else f[i][j|(1<<l)][id(l)]=min(f[i][j|(1<<l)][id(l)],f[i][j][id(k)]+(t[i+k]|t[i+l])-(t[i+k]&t[i+l]));
    					}
    				}
    			} 
    		} 
    		int ans=1e18+10;
    		for(int i=-8;i<=0;++i) ans=min(ans,f[n+1][0][id(i)]); cout<<ans<<endl; 
    		return ;
    	}
    	signed main()
    	{
    		int T=read(); while(T--) work();
    		return 0; 
    	}
    }
    signed main(){return yspm::main();}
    

    Review

    大概学到了这种加一维控制转移的题目

    其实这题目和“奇怪的道路”确实很类似

  • 相关阅读:
    linux下php环境的装配以及php storm的链接
    p4 : a problem about "./behavioral-model"
    p4factory下 targets/basic_rout
    P4安装
    第二次结对编程作业——毕业导师智能匹配
    初识GIT
    结对项目之需求分析与原型设计
    调研《构建之法》指导下的全国高校的历届软工实践作品、全国互联网+竞赛、物联网竞赛等各类全国性大学生信息化相关的竞赛平台的历届作品及其看法
    SDN 收集一下最近的资料
    软件工程的实践项目课程的自我目标
  • 原文地址:https://www.cnblogs.com/yspm/p/13417824.html
Copyright © 2011-2022 走看看