poj3740

/*
本题感觉设计很巧妙,虽然很水,但是对于dfs不熟的我感觉还是很难。通过这道题,让我又对dfs多了一份了解。
首先本题是选出一些行是每一列只含有一个1.行最多也就16,枚举也就2^16,不算太大。还不到1000000,于是很适合
用dfs。中间的used的数组很精妙,used数组就是最终的结果。通过判断used是不是全是1来判断结果。通过每一行和used比较来
确定是否可以和used并,也就是说选这一行。然后就是dfs枚举所有的情况。首先是从0开始,如果一行满足就到下一行,否则就
回溯,一直到把所有情况都枚举完毕。本题600+MS感觉效率很低。不知道所谓的十字链表是不是效率高一点。
*/

#include<iostream>
using namespace std;

int num[20][310],m,n;
bool used[310];
bool find;

bool match()
{
 int i;
 for(i=0;i<n;i++)
 {
  if(!used[i])
   return false;
 }
 return true;
}

bool check(int row)
{
 int i;
 for(i=0;i<n;i++)
 {
  if(used[i]&&num[row][i])
   return false;
 }
 for(i=0;i<n;i++)
 {
  if(num[row][i])
   used[i]=true;
 }
 return true;
}

void dfs(int s)
{
 int i,j;
 if(s>m||find)
  return;
 if(match())
 {
  printf("Yes, I found it/n");
  find=true;
  return;
 }

 for(i=s;i<m&&!find;i++)
 {
  if(check(i))
  {
   dfs(i+1);
   for(j=0;j<n;j++)
   {
    if(num[i][j])
     used[j]=false;
   }
  }
 }
}


int main()
{
 int i,j;
 while(scanf("%d%d",&m,&n)!=EOF)
 {
  for(i=0;i<m;i++)
   for(j=0;j<n;j++)
    scanf("%d",&num[i][j]);
  memset(used,0,sizeof(used));
  find=false;
  dfs(0);
  if(!find)
    printf("It is impossible/n");
 }
     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值