[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\n",ans);
	}
	return  0;
}
posted @ 2020-11-26 19:20  敌敌畏58  阅读(116)  评论(0编辑  收藏  举报