位运算加速---基于poj3740

这道题乍一看便判断出可以使用暴搜。。。

但是也很容易看出,存储啊,状态啊,都需要优化。

所以,位运算又展现了它的强大之处


这道题,如果用二进制表示每一横排的情况,一定会超过long long 的范围

所以,就改用二进制表示每一竖排的情况。

而行数总共<=16,很小,所以,考虑最变态的情况也最多有

(i<<m)-1
种选择方案(0表示不选,1表示选择)

所以,直接枚举所有的方案,用按位与的方式来确定该列是否只有一个1 。

如果找到一种选择方案让所有的列都只有一个1 ,用来标记的flag就赋为true。


我的代码如下:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m;
int lie[306];
int tt;
bool flag;
int main()
{
	freopen("easyfinding.in","r",stdin);
	freopen("easyfinding.out","w",stdout);
	
	while(scanf("%d%d",&m,&n)==2)
	{
	  memset(lie,0,sizeof(lie));
	  flag = true;
	 for(int i=1;i<=m;i++)
	   for(int j=1;j<=n;j++)
	  {
		cin>>tt;
		lie[j] = lie[j] * 2 + tt;
		if(i==m&&lie[j]==0)
		  flag = false;
		  }

   if(!flag) {printf("No\n"); continue;}//***请将Yes 和No 换成题中要求的语句
   flag=false;
   int ll=(1<<m);
   for(int i=1;i<ll;i++)
	{
	  bool bb = true;
	  for(int j=1;j<=n;j++)
	  {
		int t = (lie[j] & i);
		if ( t == 0 || (t & (t-1)) != 0 ) { bb = false; break;}
	  }
	  if( bb ) { flag = true; break;}
   }
   if( flag ) printf("Yes\n");
   else printf("No\n");
  }
   return 0;
}

		


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值