一本通-P1683-稗田阿求
题目链接
用一个数组
if(b[i]&(1<<j-1))
即i和j起冲突了。
我们还可以做一个最优化剪枝,如果当前枚举到的长度 \(t\) 和已经枚举的长度cnt满足\(cnt+m-t+1 \leq ans\),因为假设全取都不可能比当前答案大了,所以返回。退出下列代码
#include<cstdio>
#include<cstring>
#define re register
using namespace std;
const int N=101;
int ans,n,m,a[N][N],x;
long long b[N];
bool bo[N],boo;
char s[N];
inline void DFS(int t,int cnt,long long res)
{
if(cnt+m-t+1<=ans)
return;
if(t>m)
{
//printf("%d\n",cnt);
if(cnt>ans)
ans=cnt;
return;
}
if(((~res)&(1ll<<(t-1)))&&((~b[t])&(1ll<<(t-1))))
DFS(t+1,cnt+1,res|b[t]);
DFS(t+1,cnt,res);
}
int main()
{
scanf("%d%d",&n,&m);
for(re int i=1; i<=m; i++)
{
scanf("%s",s+1);
int len=strlen(s+1);
for(re int j=1ll; j<=len; j++)
{
scanf("%d",&x);
a[i][s[j]]=x;
}
}
for(re int i=1; i<=m; i++)
for(re int j=1; j<=m; j++)
{
memset(bo,false,sizeof(bo));
boo=false;
for(re char k='A'; k<='Z'; k++)
if(a[i][k]&&a[j][k]&&a[i][k]!=a[j][k])
{
boo=true;
break;
}
if(boo)
{
b[i]|=1ll<<(j-1);
continue;
}
for(re char k='A'; k<='Z'; k++)
if(a[i][k]||a[j][k])
{
if(!a[j][k])
x=a[i][k];
else
x=a[j][k];
if(!bo[x])
bo[x]=true;
else
{
boo=true;
break;
}
}
if(boo)
b[i]|=1ll<<(j-1);
}
DFS(1,0,0ll);
printf("%d\n",ans);
/*for(re int i=1; i<=m; i++)
printf("%d ",b[i]);*/
return 0;
}