• [SDOI2009]学校食堂


    题目

    题目

    做法

    状压DP。

    (f[i][j][k])表示第(i)个数字,(j)表示最后一个数字在(j+k)的位置,然后(k)用二进制表示后面的情况,对于(f[i][j][k]),设(x)为包括他以内往后(b[i]+1)位第一个没有做菜的位置,然后用(f[i][j][k])贡献给(f[x])即可。

    当然,需要提前处理每个位置的哪些二进制合法。

    #include<cstdio>
    #include<cstring>
    #define  N  1100
    using  namespace  std;
    inline  int  lowbit(int  x){return  x&-x;}
    int  f[N][10][260]/*表示这个位置自己优先搞到了*/;
    int  n,m,a[N],b[N];
    bool  he[N][260]/*表示这个屌丝哪个二进制是非常合法的*/;
    inline  int  mymin(int  x,int  y){return  x<y?x:y;}
    inline  int  mymax(int  x,int  y){return  x>y?x:y;}
    void  dfs(int  x,int  k,int  limit/*表示限制后面几位*/,int  id)//用来处理合法情况
    +
    {
    	he[id][k]=1;
    	if(x>limit)return  ;
    	dfs(x+1,k,mymin(limit,b[id+x]+x),id);
    	dfs(x+1,k^(1<<x),limit,id);
    }
    inline  int  find2(int  x){return  x==1?0:(x==2?1:(x==4?2:(x==8?3:(x==16?4:(x==32?5:(x==64?6:(x==128?7:8)))))));}
    inline  int  cost(int  x,int  y){return  (x|y)-(x&y);}
    int  ans=0;
    inline  void  solve(int  x,int  k,int  pre/*前面那个数组*/,int  co)//贡献情况
    {
    	if(x==n+1)
    	{
    		ans=mymin(ans,co);
    		return  ;
    	}
    	int  shit=(1<<(b[x]+1))-1;
    	for(int  ed=shit^k;ed;ed=ed^lowbit(ed))
    	{
    		int  y=find2(lowbit(ed));
    		if(!he[x][k^(1<<y)])continue;
    		if(f[x][y][k^(1<<y)]==-1  ||  co+cost(a[x+y],pre)<f[x][y][k^(1<<y)])f[x][y][k^(1<<y)]=co+cost(a[x+y],pre);
    	}
    }
    int  main()
    {
    //	freopen("std.in","r",stdin);
    //	freopen("vio.out","w",stdout);
    	int  T;scanf("%d",&T);
    	while(T--)
    	{
    		memset(f,-1,sizeof(f));
    		memset(he,0,sizeof(he));
    		scanf("%d",&n);ans=999999999;
    		for(int  i=1;i<=n;i++)
    		{
    			scanf("%d%d",&a[i],&b[i]);
    			b[i]=mymin(b[i],n-i);
    		}
    		for(int  i=1;i<=n;i++)dfs(0,0,7,i);
    		for(int  i=0;i<=b[1];i++)
    		{
    			if(he[1][1<<i])f[1][i][1<<i]=0;
    		}
    		for(int  i=1;i<=n;i++)
    		{
    			int  ed=(1<<(b[i]+1))-1;
    			for(int  k=1;k<=ed;k++)
    			{
    				if(!he[i][k])continue;
    				int  cnm=find2(lowbit(((1<<(b[i]+2))-1)^k));
    				for(int  t=k;t;t=t^lowbit(t))
    				{
    					int  j=find2(lowbit(t));
    					if(f[i][j][k]!=-1)solve(cnm+i,k>>cnm,a[i+j],f[i][j][k]);
    				}
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return  0;
    }
    
  • 相关阅读:
    Dell PowerEdge服务器RAID卡驱动下载
    Cent OS yum 安装 Adobe flash player
    如何在安全模式下创建新管理员账户?
    chkdsk 和sfc.exe修复命令
    右下角弹出"Windows-延缓写入失败"或者"xxx-损坏文件 请运行Chkdsk工具"
    VMware NAT模式 Cent OS IP配置
    sublime Text2 2.0.2 build 2221 64位 破解(已测试)
    Windows Server 2008 R2 配置Exchange 2010邮件服务器
    openGL深度缓冲区问题
    glRotatef 转动方向
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/14044055.html
Copyright © 2020-2023  润新知