easyfinding(codevs 3280)
题目描述 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
(codevs有一个数据让我陷入死循环了,所以在程序中略有改动)
View Code
#include<cstdio> #include<iostream> #include<vector> #include<cstring> #define M 310 using namespace std; int map[M][M],n,m,head,tail; int v[M][M],q[M],flag; struct node { int vis[M]; };node a[M]; int ok(int x) { for(int i=1;i<=m;i++) if(!a[x].vis[i])return 0; return 1; } void init() { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&map[i][j]); if(map[i][j])v[i][++v[i][0]]=j; } } while(head<=tail) { if(tail>10*n)return;//防止死循环(其实就是作弊 >_<~~~) for(int i=1;i<=n;i++) { q[++tail]=i; 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]]) ff=1; if(!ff) { for(int j=1;j<=v[i][0];j++) a[tail].vis[v[i][j]]=1; if(ok(tail)) { printf("Yes\n"); flag=1; return; } } else tail--; } head++; } } int main() { while(scanf("%d%d",&n,&m)==2) { memset(a,0,sizeof(a)); memset(v,0,sizeof(v)); memset(q,0,sizeof(q)); head=0;tail=0;flag=0; init(); if(!flag)printf("No\n"); } return 0; }