一本通-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;
}

posted @ 2019-11-24 18:27  蒟蒻wjr  阅读(303)  评论(0编辑  收藏  举报