这题每次求的时候必须在满足条件的情况中选,明显是队列优化的模型,如果枚举所有情况,tle不解释。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#define ll __int64
#define eps 1e-10
#define maxn 305
#define L ((1<<22)+1)
using namespace std;
int g[33][1000],value[(1<<22)+10],len[(1<<22)+10];
int v[33],q[(1<<22)+10];
int is[(1<<22)+1][2];
void print(int x)
{
if(x<2) printf("%d",x);
else
{
print(x/2);
printf("%d",x%2);
}
}
void init()
{
len[0]=0;
for(int i=1; i<(1<<22); i++)
{
for(int j=0; j<22; j++)
{
if(i&(1<<j))
{
value[i]=value[i^(1<<j)]+j+1;
len[i]=len[i^(1<<j)]+1;
break;
}
}
if(value[i]<=22)
g[value[i]][++g[value[i]][0]]=i;
}
}
int main()
{
init();
int n,m,tt=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m) break;
for(int i=1;i<=m;i++)
{
scanf("%d",&v[i]);
}
int qs,qe,V;
qs=0,qe=1,q[0]=0;
int ans=0,limit=(1<<n);
for(int i=1;i<=m;i++)
{
int flag=0;
V=v[i];
int size=qe;
for(;qs!=size;qs++)
{
int pre=q[(qs%L)];//循环队列来缩小内存
for(int j=1;j<=g[V][0];j++)
{
int tmp=g[V][j];
if(tmp>=limit) continue;
if((pre&tmp)==0)
{
int next=(pre|tmp);
if(is[next][0]!=tt||is[next][1]!=i)//出现次数可能不止一次,去重
{
is[next][0]=tt;
is[next][1]=i;
q[qe%L]=next;
qe++;
ans=max(ans,len[next]);
}
}
}
}
}
printf("Game %d: ",tt++);
printf("%d\n",ans);
}
return 0;
}