1 1 * 3 5 *@*@* **@** *@*@* 1 8 @@****@* 5 5 ****@ *@@*@ *@**@ @@@*@ @@**@ 0 0
0 1 22
解题报告:
这个题是一道深搜的典型题,也是八方搜索,只要八个方向有一个方向满足,就继续递归,遍历下一个符合条件的八个方向。其实深搜的思想也正在于此。
这个题一开始没有想出来的原因是,没有正确的明确理解深搜的意思(orz其实很多人都是在做题中,把这个题的题意了解清楚了,才会真正借用这个题领悟到定义的本质,或者发现自己原来对于某个定义理解是错误的,这样印象就会更深,理解也会更加透彻)。
转到这个题目上面,题意是说@代表油田,*代表空。遇到有@的,如果八个方向,上下左右斜线都有油田那么他们就算一个,否则算多个,最后是输出有多少种油田的数目。
好了,下面是具体步骤分析:要从dfs函数外面就进行判断,如果是@才可以dfs,否则假如说在dfs里面才进行判断,那么如果当前是*,进行dfs,它的八个方向中有一个是@,这样也会继续搜索,和题意不符,所以必须要在外面就进行判断。而且假如被访问过,就要把它设为*,等价于vis=1,这样接下来就不会被继续访问了。
具体思路图示如下(一定要注意顺序问题,即深搜的递归情况,一直往下搜)
有一个地方的bug,提交了8次才过,还是字符串的问题(此时好想说日了狗啊。。真的改的多艰难)知道为什么吗?还是因为字符串基础打得不牢固,二维数组scanf(”%s“,mp[1])默认是从mp[1][0]开始的,但是我是从[1][1]开始定义的啊啊啊啊啊啊!!!(此时内心悲愤之情难以言喻,恩,还是自己c语言数组基础没有打好,怪自己,欠打啊。。此时声泪俱下。不过也不能用%c啊,那个不好处理空格回车的,也容易错的。真的好多事情都是自己作死的。。),所以要for(i=1;i<=n;i++)scanf("%s",mp[i]+1),一定不要忘了+1啊啊啊啊!!!
恩,到了上自己代码的时候了。。此时我是饱含泪水的,明天一天不想说话好么。。
#include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define N 100+10 //不要开太大,比如10000就不行,因为是平方,会更大,开的大了会MLE int m,n,vis[N][N],ans; char mp[N][N]; int a[8]={-1,-1,0,1,1,1,0,-1}; int b[8]={0,1,1,1,0,-1,-1,-1}; void dfs(int x,int y) { int nx,ny; vis[x][y]=1; for(int i=0;i<8;i++) { nx=x+a[i]; ny=y+b[i]; if(nx>0&&nx<=m&&ny>0&&ny<=n&&vis[nx][ny]==0&&mp[nx][ny]=='@') { dfs(nx,ny); mp[x][y]='*';//这个点遍历过了就要设为*,以后不会再遍历到了 } } } int main() { while(scanf("%d%d",&m,&n)!=EOF) { if(m==0&&n==0) break; memset(mp,0,sizeof(mp)); memset(vis,0,sizeof(vis)); ans=0; for(int i=1;i<=m;i++) { scanf("%s",mp[i]+1); //提交了八次的错误啊!!一定要记住字符串数组的下标,从0开始啊 } for(int x=1;x<=m;x++) { for(int y=1;y<=n;y++) { if(mp[x][y]=='@'&&vis[x][y]==0) //一定要先判断是否是@啊 { dfs(x,y); ans++; //这个不要加在里面,因为是最终多少次 } } } printf("%d\n",ans); } return 0; }
恩,上一份5210的代码,学习一下。。#include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX / 10) #define clr(arr, val) memset(arr, val, sizeof(arr)) #define pb push_back #define sz(a) ((int)(a).size()) using namespace std; typedef set<int> si; typedef vector<int> vi; typedef map<int, int> mii; typedef pair<int, int> pii; typedef long long ll; const double esp = 1e-5; #define N 110 int n, m, vis[N][N]; int dx[] = {0, 0, -1, 1, 1, 1, -1, -1}; int dy[] = {1, -1, 0, 0, 1, -1, 1, -1}; char mp[N][N]; void dfs(int x, int y) { vis[x][y] = 1; for (int i = 0; i < 8; ++i) { int nx = x + dx[i]; int ny = y + dy[i]; if (mp[nx][ny] == '@' && !vis[nx][ny]) { dfs(nx, ny); } } } int main(int argc, char *argv[]) { while (scanf("%d%d", &n, &m) != EOF) { if (n == 0 && m == 0) { break; } clr(mp, 0); for (int i = 1; i <= n; ++i) { scanf("%s", mp[i] + 1); } clr(vis, 0); int ans = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (!vis[i][j] && mp[i][j] == '@') { dfs(i, j); ++ans; } } } printf("%d\n", ans); } return 0; }