3280 easyfinding

3280 easyfinding

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
题目描述 Description

 给一个M 行N  列的01 矩阵,让你选出一些行 (不一定选出全部行)使得每一列都有 
且只有一个1。其中M<= 16,N<=300 。

输入描述 Input Description

    输入含有多组数据。以文件结束符(eof )为结束。最多会有500 组。 
    输入之间会有梯度,也就是不是每组输入都是500 组。 
    对每组数据,第一行:两个由空格隔开的整数M 和N 。然后是M 行每行N  个等于0 
或者等于1 的整数,整数之间由空格隔开。

输出描述 Output Description

对每组数据输出一行,如果可以达到题中要求,输出Yes 否则输出No  。均不包括引号。

样例输入 Sample Input

3 3 
0 1 0 
0 0 1 
1 0 0 
4 4 
0 0 0 1 
1 0 0 0 
1 1 0 1 
0 1 0 0

样例输出 Sample Output

Yes 
No

数据范围及提示 Data Size & Hint

注意时间复杂度

分类标签 Tags 点此展开 

 
第一次没读明白题目,任选几行组成(不一定连续)
用枚举做就AC了一个点
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int map[17][301];
int n,m;
void dfs(){
    int flag=0;
    for(int i=1;i<=m;i++)
        for(int j=i;j<=m;j++){
            for(int k=1;k<=n;k++){
                int num=map[j][k]-map[i-1][k];
                if(num!=1) break;
                if(k==m){flag=1;printf("Yes
");return ;}
            }
        }
    if(!flag) printf("No
");
}
int main(){
    while(scanf("%d%d",&m,&n)==2){
        memset(map,0,sizeof map);
        for(int i=1,x;i<=m;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&x),map[i][j]=map[i-1][j]+x;
            }
        }
        dfs();
    }
    return 0;
} 

正解AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 310
struct node{
    int vis[N];
}a[N];
int n,m,head,tail,flag;
int v[20][N];
int ok(int x){//验证 
    for(int i=1;i<=m;i++)
        if(!a[x].vis[i])return 0;
    return 1;
}
void bfs(){
    while(head<=tail){//不明确第一个状态,so"<=" 
        if(head>10*n) return ;//防止死循环 
        for(int i=1;i<=n;i++){
            ++tail;
            for(int j=1;j<=m;j++)//回溯 
                a[tail].vis[j]=a[head].vis[j];
            int ff=0;
            for(int j=1;j<=v[i][0];j++)
                if(a[tail].vis[v[i][j]]){//有1 - 不满足 
                    ff=1;break;
                }
            if(!ff){
                for(int j=1;j<=v[i][0];j++)
                    a[tail].vis[v[i][j]]=1;//更新vis 
                if(ok(tail)){
                    flag=1;
                    printf("Yes
");
                    return ;
                }
            }
            else
                tail--;//当前不满足,回溯 
        }
        head++;
    }
}
int main(){
    while(scanf("%d%d",&n,&m)==2){
        memset(a,0,sizeof a);
        memset(v,0,sizeof v);
        for(int i=1,x;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&x);
                if(x) v[i][++v[i][0]]=j;//模拟动态数组,v[i][++v[i][0]]=j;记录第i行第v[i][0]个1的列号j 
            }
        }
        head=0;tail=0;flag=0;
        bfs();
        if(!flag) printf("No
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/5582864.html