这道题乍一看便判断出可以使用暴搜。。。
但是也很容易看出,存储啊,状态啊,都需要优化。
所以,位运算又展现了它的强大之处
这道题,如果用二进制表示每一横排的情况,一定会超过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;
}