标签:dfs
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16482 | Accepted: 4476 |
Description
Input
Output
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, I found it It is impossible
Source
解题思路:
题意为给出n*m的01矩阵,问能不能从中选出一些行,使得这些行组成的新矩阵中,每列有且只有一个1.
本题用Dlx可解,明显的完全覆盖问题。这里练习DFs,用DFS按照行号递增的顺序枚举行就可以.一开始犯了一个很严重的错误,就是没有按行号递增的顺序,导致了重复,其实 1 2 5和 5 1 2其实是一样的,所以DFS(int row), 参数是行号,下一层递归为DFs(row+1), 每次进入DFs都要首先判断是否符合题意,即新矩阵每列有且只有一个1,用vis[j]数组表示新矩阵中第j列是否已经有一个1,如果满足该条件,就不用往下继续递归了,直接标记成功,return即可。
通过这道题,加深了对递归的理解,感觉只要想明白,递归也不是那么难理解。
假设当n=4时,搜索的行号是按这样的顺序:
1
1 2
1 2 3
1 2 3 4
1 2 4
1 3
1 3 4
1 4
2
2 3
2 3 4
2 4
3
3 4
4
代码:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> #include <stdlib.h> #include <cmath> #include <iomanip> #include <vector> #include <set> #include <map> #include <stack> #include <queue> #include <cctype> using namespace std; #define ll long long const int maxn=18; const int maxm=302; int mp[maxn][maxm]; int n,m; bool vis[maxm];// vis[i]表示第i列是否有一个1了 bool ok; int hash[maxn];//第i行有多少个1 bool yes(int row)//判断第row行可不可行 { for(int i=1;i<=m;i++) if(mp[row][i]&&vis[i]) return false; return true; } void DFS(int cnt,int row)//参数cnt为当前所选的行里面列已经有多少个1,row是当前选择的第几行 { if(cnt==m||(row>n&&cnt==m))///这里也要注意,当选择的行号大于n时,也要判断已选择的行号是否满足题意 { ok=1; return; } if(row>n) return; for(int i=row;i<=n;i++)///所犯的一个很严重的错误,一开始写成i=1了,重复了,行号是按照递增的顺序来选择的,1 5 8和5 1 8是同一种情况 { if(yes(i)) { for(int j=1;j<=m;j++) { if(mp[i][j]) vis[j]=1; } DFS(cnt+hash[i],i+1); if(ok) break; for(int j=1;j<=m;j++) { if(mp[i][j]) vis[j]=0; } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(hash,0,sizeof(hash)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&mp[i][j]); if(mp[i][j]) hash[i]++; } ok=0; memset(vis,0,sizeof(vis)); DFS(0,1); if(ok) printf("Yes, I found it\n"); else printf("It is impossible\n"); } return 0; }
[ACM] POJ 3740 Easy Finding (DFS)
标签:dfs
原文地址:http://blog.csdn.net/sr_19930829/article/details/42706227