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\n");return ;} } } if(!flag) printf("No\n"); } 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\n"); 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\n"); } return 0; }
时间: 2024-07-29 09:17:03