SDNU-ACM-ICPC 2020 DFS&BFS (咕咕o(≧v≦)o)
传送门
Red and Black
题意:
m * n的地图,#不可以走,.可以走,@是起点,问你从@开始能走到的点的个数是多少
方法1:dfs
这个题相当于问的是从起点开始能走到的位置,跟路径没有关系,只要dfs整个地图就可以,而且每个点只需要走一遍,我们就判断如果是‘.’并且没被标记过,就更新答案,然后标记一下
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, m, xx, yy, ans;
char tr[25][25];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};
bool vis[25][25];
void dfs(int x, int y){
if(tr[x][y] == '.' && vis[x][y] == 0){
ans++;
vis[x][y] = 1;
}
else return;
for(int i = 0; i < 4; ++i){
xx = x + dx[i];
yy = y + dy[i];
dfs(xx, yy);
}
}
int main(){
while(cin>>n>>m && n != 0 && m != 0){
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
ans = 0;
swap(n, m);//本题是m行n列,将其转化成n行m列会好写点
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
scanf(" %c",&tr[i][j]);
if(tr[i][j] == '@'){
xx = i; yy = j;
tr[i][j] = '.';
}
}
dfs(xx, yy);
cout<<ans<<endl;
}
return 0;
}
方法2:bfs
因为每个点只走一遍,就很符合bfs的特点
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, m, xx, yy, ans;
char tr[25][25];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};
bool vis[25][25];
struct ran{
int x, y;
};
queue<ran>q;
bool judge(int x, int y){
if(x > n || x < 1 || y > m || y < 1)return false;
else if(vis[x][y])return false;
else if(tr[x][y] == '#')return false;
else return true;
}
void bfs(){
ran now, next;
now.x = xx; now.y = yy;
q.push(now);
vis[now.x][now.y] = 1;
while (!q.empty()) {
now = q.front();q.pop();
if(tr[now.x][now.y] == '.'){
ans++;
}
for(int i = 0; i < 4; ++i){
next.x = now.x + dx[i];
next.y = now.y + dy[i];
if(!judge(next.x, next.y))continue;
vis[next.x][next.y] = 1;
q.push(next);
}
}
}
int main(){
while(cin>>n>>m && n != 0 && m != 0){
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
ans = 0;
swap(n, m);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
scanf(" %c",&tr[i][j]);
if(tr[i][j] == '@'){
xx = i; yy = j;
tr[i][j] = '.';
vis[i][j] = 1;
}
}
bfs();
cout<<ans<<endl;
}
return 0;
}
B - 棋盘问题
题意:
在给定棋盘上放棋子,其中#位置不能放,且你放的所有的棋子中的任意两个,不能在同一行或同一列,问你总共有多少种摆法
思路:
这个题只能dfs,按行搜,
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, k, xx, yy, ans, step;
bool vis[10];
char tr[10][10];
bool judge(int x, int y){
if(x > n || x < 1 || y > n || y < 1)return false;
else if(tr[x][y] == '#')return false;
else return true;
}
void dfs(int x){
if(step == k){
ans++;
return;
}
if(x > n)return;//这个和下面的那个是配对的,当你一直跳到下一行就可以会跳出去了
for(int y = 1; y <= n; ++y){
if(judge(x, y))continue;
if(vis[y])continue;
vis[y] = 1;
step++;
dfs(x + 1);
step--;
vis[y] = 0;
}
dfs(x + 1);//可能这个行没有点可以用,就得手动跳到下一行
}
int main(){
while (cin>>n>>k && n != -1 && k != -1) {
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
ans = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
scanf(" %c",&tr[i][j]);
dfs(1);
cout<<ans<<endl;
}
}
C - Dungeon Master
题意:
三维迷宫,问你能不能从S走到E,只能上下左右前后走,而且不能走#格
思路:
bfs就完事了,输入的是一层一层的,所以对于xyz会有点奇怪
一定一定一定一定一定要记得给他么的狗队列清0 ,不然会wa的很惨(只有亲身经历后才知道有多崩溃!呜呜呜)
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int h, n, m, xx, yy, zz, ans;//h是高度,n是行数,m是列数
char tr[35][35][35];
bool vis[35][35][35];
int dx[] = {1, 0, -1, 0, 0, 0};
int dy[] = {0, 1, 0, -1, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};
bool judge(int z, int x, int y){
if(z > h || z < 1 || x > n || x < 1 || y > m || y < 1)return false;
else if(vis[z][x][y])return false;
else if(tr[z][x][y] == '#')return false;
else return true;
}
struct ran{
int x, y, z, step;
};
queue<ran>q;//千万千万要给队列初始化!
int bfs(){
ran now, next;
now.z = zz;now.x = xx;now.y = yy;now.step = 0;
q.push(now);
vis[now.z][now.x][now.y] = 1;
while (!q.empty()) {
now = q.front();
q.pop();
if(tr[now.z][now.x][now.y] == 'E'){
return now.step;
}
for(int i = 0; i < 6; ++i){
next.z = now.z + dz[i];
next.x = now.x + dx[i];
next.y = now.y + dy[i];
if(!judge(next.z, next.x, next.y))continue;
vis[next.z][next.x][next.y] = 1;
next.step = now.step + 1;
q.push(next);
}
}
return 0;
}
int main(){
while (cin>>h>>n>>m && (h + n + m)) {
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
while (!q.empty()) {//千万要给队列初始化!
q.pop();
}
ans = 0;
for(int i = 1; i <= h; ++i)
for(int j = 1; j <= n; ++j){
scanf(" %s",tr[i][j] + 1);
for(int k = 1; k <= m; ++k){
if(tr[i][j][k] == 'S'){
zz = i;xx = j;yy = k;
tr[i][j][k] = '.';
}
}
}
ans = bfs();
if(ans)
printf("Escaped in %d minute(s).\n",ans);
else
printf("Trapped!\n");
}
return 0;
}
D - Catch That Cow
题意:
在0到1e5的道路上,农夫要去抓牛,牛不动,农夫可以在一分钟内可以向前移动一格或者向后移动一个,或者到达2倍位置的地方,问最短多长时间抓到牛
思路:
一维bfs,注意不能走重复,因为如果重复了就代表这绝对不是最短距离
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, k;
bool vis[MAX];
struct ran{
int x, step;
};
queue<ran>q;
bool judge(int x){
if(x > 1000001 || x < 0)return false;
else if(vis[x])return false;
else return true;
}
int bfs(){
ran now, next;
now.x = n;now.step = 0;
q.push(now);
vis[now.x] = 1;
while (!q.empty()) {
now = q.front();q.pop();
if(now.x == k){
return now.step;
}
next.x = now.x * 2;next.step = now.step + 1;
if(judge(next.x)){
q.push(next);
vis[next.x] = 1;
}
next.x = now.x - 1; next.step = now.step + 1;
if(judge(next.x)){
q.push(next);
vis[next.x] = 1;
}
next.x = now.x + 1; next.step = now.step + 1;
if(judge(next.x)){
q.push(next);
vis[next.x] = 1;
}
}
return 0;
}
int main(){
cin>>n>>k;
cout<<bfs()<<endl;
}
G - 胜利大逃亡
题意:
三维地图,问你能不能在规定时间内从(1,1,1)走到(h, n, m)
思路:
三维bfs即可,同样的xyz的顺序不是那么顺
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int T, n, m, h, t;
int tr[55][55][55];
bool vis[55][55][55];
int dx[] = {1, 0, -1, 0, 0, 0};
int dy[] = {0, 1, 0, -1, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};
struct ran{
int x, y, z, step;
};
queue<ran>q;
bool judge(int z, int x, int y){
if(z > h || z < 1 || x > n || x < 1 || y > m || y < 1)return false;
else if(vis[z][x][y])return false;
else if(tr[z][x][y] == 1)return false;
else return true;
}
void init(){//初始化
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
while (!q.empty()) {
q.pop();
}
}
int bfs(){
ran now, next;
now.x = 1;now.y = 1;now.z = 1;now.step = 0;
q.push(now);
vis[1][1][1] = 1;
while (!q.empty()) {
now = q.front();q.pop();
if(now.z == h && now.x == n && now.y == m){
return now.step;
}
for(int i = 0; i < 6; ++i){
next.z = now.z + dz[i];next.x = now.x + dx[i];next.y = now.y + dy[i];
if(!judge(next.z, next.x, next.y))continue;
vis[next.z][next.x][next.y] = 1;
next.step = now.step + 1;
q.push(next);
}
}
return 0;
}
int main(){
cin>>T;
while (T--) {
init();
cin>>h>>n>>m>>t;
for(int i = 1; i <= h; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= m; ++k)
tr[i][j][k] = IntRead();
int ans = bfs();
if(ans != 0 && ans <= t)cout<<ans<<endl;
else cout<<-1<<endl;
}
}
H - A计划
题意:
在三维图内救公主,从(0,0,0)出发,不能走*,遇到#就会传送到另一层的同一个位置,如果传送过去的地方是#就会直接撞死,问你能不能在t时刻找到公主
思路:
bfs,遇到传送门就得特判,另一层的同一个位置不可以是*或#
这个题说的是能不能在t时刻找到公主,但ac码是能不能在t时刻之前找到,我就有点懵o(︶︿︶)o
还有就是最后输出的是YES和NO,而不是最短时间!靠
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int T, n, m, h, t, xx, yy, zz;
char tr[5][55][55];
bool vis[5][55][55];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
struct ran{
int x, y, z, step;
};
queue<ran>q;
bool judge(int z, int x, int y){
if(x > n || x < 1 || y > m || y < 1 || z < 1 || z > 2)return false;
else if(vis[z][x][y])return false;
else if(tr[z][x][y] == '*')return false;
else return true;
}
void init(){
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
while (!q.empty()) {
q.pop();
}
}
int bfs(){
ran now, next;
now.z = zz;now.x = xx;now.y = yy;now.step = 0;
q.push(now);vis[zz][xx][yy] = 1;
while (!q.empty()) {
now = q.front();q.pop();
if(tr[now.z][now.x][now.y] == 'P'){
return now.step;
}
for(int i = 0; i < 4; ++i){
next.z = now.z;next.x = now.x + dx[i];next.y = now.y + dy[i];
if(tr[next.z][next.x][next.y] == '#'){
if(next.z == 1)next.z++;
else if(next.z == 2)next.z--;
if(tr[next.z][next.x][next.y] == '#')continue;
if(!judge(next.z, next.x, next.y))continue;
vis[next.z][next.x][next.y] = 1;
next.step = now.step + 1;
q.push(next);
}
else {
if(!judge(next.z, next.x, next.y))continue;
vis[next.z][next.x][next.y] = 1;
next.step = now.step + 1;
q.push(next);
}
}
}
return 0;
}
int main(){
cin>>T;
while (T--) {
init();
cin>>n>>m>>t;
//cout<<n<<m<<t;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= m; ++k){
scanf(" %c",&tr[i][j][k]);
if(tr[i][j][k] == 'S'){
zz = i;xx = j; yy = k;
}
}
int ans = bfs();
if(ans != 0 && ans <= t)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
I - Sum It Up
题意:
m个数,从中找任意多个数,要保证其和等于n,且不重复的情况的个数,并降序输出每种情况,每种情况也是降序输出
思路:
首先因为要降序输出,所以得对数列进行降序排列,然后通过dfs进行搜索,两个变量:star表示走到了哪个位置,sum表示到目前为止的和
最重要的其实是去重,这里通过star来控制就能实现,同时对于每次return后要去掉这之后所有与他相同的数字
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, m, num, ans;
int tr[100], ar[100];
bool vis[100];
void init(){
memset(tr, 0, sizeof(tr));
memset(vis, 0, sizeof(vis));
memset(ar, 0, sizeof(ar));
ans = 0;num = 0;
}
bool cmp(int x, int y){
return x > y;
}
void dfs(int star, int sum){
if(sum > n)return;
else if(sum == n){
ans = 1;
for(int i = 1; i <= num; ++i){
if(i != num)cout<<ar[i]<<'+';
else cout<<ar[i]<<endl;
}
}
for(int i = star; i <= m; ++i){
ar[++num] = tr[i];
vis[i] = 1;
dfs(i + 1, sum + tr[i]);
vis[i] = 0;
num--;
while (i + 1 <= m && tr[i] == tr[i + 1]) {
i++;
}
}
}
int main(){
while (cin>>n>>m && (n + m)) {
init();
for(int i = 1; i <= m; ++i)cin>>tr[i];
sort(tr + 1, tr + 1 + m, cmp);
printf("Sums of %d:\n",n);
dfs(1, 0);
if(!ans)cout<<"NONE\n";
}
}
J - N皇后问题
思路:
两个皇后不能在行或列或对角线上,对角线有两个,我们还是同B题一样按行搜,对每行的列进行dfs,这次vis数组要开二维的,好记录列与两个对角线是否标记过,对于对角线相当于一个一次函数,而我们标记的是他的y = kx + b中的b,k = 1或-1,b就等于x + y或 x - y,但是x - y可能会出现负数,所以我们可以加上n,这样就可以保证下标大于0,但是要给数组开的稍微大一点点,这个数n + x - y最大是20,超过20就可以(我第一遍开了个15,就直接wa了,艹),再就是要注意用数组存答案,然后人家问什么就直接输出
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int n, tr[15];
bool vis[3][100];
void init(){
memset(vis, 0, sizeof(vis));
}
bool judge(int x, int y){
if(vis[0][y])return false;
else if(vis[1][x + y])return false;
else if(vis[2][n + x - y])return false;
else return true;
}
void dfs(int x){
if(x == n){
tr[n]++;
return;
}
for(int y = 1; y <= n; ++y){
if(!judge(x, y))continue;
vis[0][y] = 1;
vis[1][x + y] = 1;
vis[2][n + x - y] = 1;
dfs(x + 1);
vis[0][y] = 0;
vis[1][x + y] = 0;
vis[2][n + x - y] = 0;
}
}
int main(){
for(int i = 1; i <= 10; ++i){
n = i;
init();
dfs(0);
}
while (cin>>n && n) {
cout<<tr[n]<<endl;
}
}
K - Oil Deposits
题意:
给你一个地图,@代表油田,其他点代表石头,问你总共有几个油田,其中一个点可以和周围八个点相连
思路1:
dfs:直接怼暴力,搜整个图,遇到一个@且未经过标记的就开始dfs,dfs的时候要对所有相连的@进行标记,最好输出ans即可
注意,这次dfs要在刚开始就标记,因为如果写在循环判断后面,就可能你搜 的点是@但周围八个点全是石头,就不会更新答案滴
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
char tr[105][105];
bool vis[105][105];
int n, m, ans, cnt;
int dx[] = {1, 0, -1, 0, -1, 1, 1, -1};
int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
void init(){
memset(vis, 0, sizeof(vis));
memset(tr, 0, sizeof(tr));
ans = 0;
}
bool judge(int x, int y){
if(x > n || x < 1 || y > m || y < 1)return false;
else if(vis[x][y])return false;
else if(tr[x][y] == '*')return false;
else return true;
}
void dfs(int x, int y){
if(tr[x][y] == '@'){
cnt = 1;
vis[x][y] = 1;
}
for(int i = 0; i < 8; ++i){
int xx = x + dx[i];
int yy = y + dy[i];
if(!judge(xx, yy))continue;
//vis[xx][yy] = 1;
//cnt = 1;
dfs(xx, yy);
//vis[xx][yy] = 0;
}
}
int main(){
while (cin>>n>>m && (n + m)) {
init();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf(" %c", &tr[i][j]);
for(int i = 1; i <= n; ++i)//直接暴力搜图
for(int j = 1; j <= m; ++j){
if(!vis[i][j] && tr[i][j] == '@'){
cnt = 0;
dfs(i, j);
if(cnt)ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
思路2:
这个题每个点只需要走一次,所以也可以用bfs,思路和dfs差不多
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
char tr[105][105];
bool vis[105][105];
int n, m, ans, cnt;
int dx[] = {1, 0, -1, 0, -1, 1, 1, -1};
int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
struct ran{
int x, y;
};
queue<ran>q;
void init(){//初始化
memset(vis, 0, sizeof(vis));
memset(tr, 0, sizeof(tr));
ans = 0;
}
bool judge(int x, int y){//判断条件
if(x > n || x < 1 || y > m || y < 1)return false;
else if(vis[x][y])return false;
else if(tr[x][y] == '*')return false;
else return true;
}
void bfs(int x, int y){
if(tr[x][y] == '@' && vis[x][y] == 0){//更新答案
cnt = 1;
}
while (!q.empty()) {//清空队列!!!
q.pop();
}
ran now, next;
now.x = x; now.y = y;
q.push(now);
vis[x][y] = 1;
while (!q.empty()) {
now = q.front();q.pop();
for(int i = 0; i < 8; ++i){
next.x = now.x + dx[i];
next.y = now.y + dy[i];
if(!judge(next.x, next.y))continue;
q.push(next);
vis[next.x][next.y] = 1;
}
}
}
int main(){
while (cin>>n>>m && (n + m)) {
init();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf(" %c",&tr[i][j]);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(!vis[i][j] && tr[i][j] == '@'){
cnt = 0;
bfs(i, j);
if(cnt)ans++;
}
}
cout<<ans<<endl;
}
}
L - 变形课
题意:
给你一堆字符串,问你能不能按成语接龙的方式从b连到m
思路:
对dfs的灵活运用
这个题有不止一个b开头的,如果暴力的话就得循环找每个b开头的,再去暴力,所以我们dfs也得这样,再者我们需要用两个数组,一个存字符串开头的字符,一个存字符串最后一个字符,dfs去跑搜的字符串的位置
注意答案输出的时候还tm有个句号,艹
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 1000000 + 7
#define endl '\n'
#define mod 1e9+7;
typedef long long ll ;
//不开longlong见祖宗!
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
char star[MAX], end1[MAX];
bool vis[MAX];
string s;
int n, ans;
void dfs(int k){
if(ans == 1){//找到答案就返回
return;
}
if(end1[k] == 'm'){//找到了m
ans = 1;
return;
}
for(int i = 1; i <= n; ++i){
if(vis[i])continue;
if(star[i] == end1[k]){//判断能不能接龙成功
vis[i] = 1;
dfs(i);
vis[i] = 0;
}
}
}
void init(){//初始化很重要
memset(vis, 0, sizeof(vis));
memset(star, 0, sizeof(star));
memset(end1, 0, sizeof(star));
ans = 0;n = 0;
}
int main(){
while (cin>>s) {
if(s [0] != '0'){//判断输入的是不是0
star[++n] = s[0];
end1[n] = s[s.size() - 1];
}
else if(s[0] == '0'){//是0就开始搜索
for(int i = 1; i <= n; ++i){
if(star[i] == 'b'){
dfs(i);
}
if(ans == 1){//如果ans=1就直接跳出就可以了,没必要一直搜了
break;
}
}
if(ans)cout<<"Yes.\n";
else cout<<"No.\n";
init();//搜完记得初始化,以便下次再搜
}
}
return 0;
}
写在最后:
这份搜索题是20年十一月初的,一不小心鸽了四个月⁄(⁄ ⁄ ⁄ω⁄ ⁄ ⁄)⁄,深感愧疚,之前对搜索很抵触,不过上次牛客比赛遇到了个搜索题,写个dfs却wa了好多次才过,最后才发现是retuen后vis忘归0了,就感觉再不练练的话就说不过去了,现在补上了,总体来说对那种板子题还是能写的过去,不过要是换个题型就不太行了(╥﹏╥)。噢对了,还有两个英文题太懒的搞了,就没搞,请call me 小懒猪(*≧ω≦)