B - Red and Black // dfs 深度搜索

本文介绍了一个使用深度优先搜索(DFS)算法的经典案例——计算在一个由红色和黑色方砖组成的矩形房间中,从特定黑色砖块出发可以到达的黑色砖块总数。文章通过具体的输入输出示例详细解释了算法实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B - Red and Black


There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.

Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.
Output
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
思路:简单的dfs搜索,判断这个@符号的上下左右四个方向的位置是否为  ' . ' ,如果为 ' . ',的话,就可一走,如果不是的话,就要看其他方向,找出其中最多可以走多少。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
using namespace std;
int m,n;//n代表列,m代表行
int cnt;
char mp[100][100];
void dfs(int p,int q){//p是行 q是列
  if(mp[p][q]!='.' || p<0 || q<0 || p>=m||q>=n){
    return ;
  }else{
      cnt++;
      mp[p][q]='#';
  dfs(p-1,q);
  dfs(p,q+1);
  dfs(p+1,q);
  dfs(p,q-1);
  }
}
int main(){
int i,j;
while(scanf("%d%d",&n,&m)!=EOF){
     cnt=0;
    memset(mp,0,sizeof(mp));
    if(n==0 && m==0){
        break;
    }
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            cin>>mp[i][j];
        }
        //getchar();
    }
  for(i=0;i<m;i++){
    for(j=0;j<n;j++){
        if(mp[i][j]=='@'){
           mp[i][j]='.';
            dfs(i,j);
        }
    }
  }
  cout<<cnt<<endl;
}
return 0;
}

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
char mp[100][100];
int cnt;
int n,m;
void f(char mp[100][100],int x,int y){
  mp[x][y]='#';
  if(x+1<m && mp[x+1][y]=='.'){
    cnt++;
    f(mp,x+1,y);
  }
   if(x-1>-1 && mp[x-1][y]=='.'){
    cnt++;
    f(mp,x-1,y);
  }
   if(y+1<n && mp[x][y+1]=='.'){
    cnt++;
    f(mp,x,y+1);
  }
   if(y-1>-1 && mp[x][y-1]=='.'){
    cnt++;
    f(mp,x,y-1);
  }
}
int main(){
int i,j;
 while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0 ||m==0)
           break;
       for(i=0;i<m;i++){
        scanf("%s",&mp[i]);
       }
       for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            if(mp[i][j]=='@'){
                cnt=1;
                f(mp,i,j);
                printf("%d\n",cnt);
            }
        }
       }
 }
}

自己的代码

经典的搜索题目,深度优先搜索,其描述如下:
void dfs()
{
   for(所有的邻接节点)
  {
      if(节点没有被遍历)
      {
          标记此节点;
          dfs(此节点);
      }
  }
}

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
char mp[21][21];
int v[21][21];
int m,n;
int cnt=0;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
//int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int w,int e)
{
    for(int i=0;i<4;i++)
    {
        int ww=w+dir[i][0];
        int ee=e+dir[i][1];
       // cout<<"ww* "<<ww<<"ee* "<<ee<<endl;
        if(mp[ww][ee]=='.'&&ww>=0&&ww<n&&ee>=0&&ee<m)
        {
            cnt++;
            v[ww][ee]=1;
            mp[ww][ee]='#';
           // cout<<"ww= "<<ww<<"ee= "<<ee<<endl;
            dfs(ww,ee);
        }
    }
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int x,y;
        memset(mp,0,sizeof(mp));
        memset(v,0,sizeof(v));
        if(m==0 ||n==0)
            break;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>mp[i][j];
                if(mp[i][j]=='@')
                {
                    x=i;
                    y=j;
                }
            }
        }
      // cout<<"x= "<<x<<"y= "<<y<<endl;
        mp[x][y]='#';
        cnt=1;
        dfs(x,y);
        printf("%d\n",cnt);
    }
    return 0;
}

或者  

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
char mp[21][21];
int v[21][21];
int m,n;
int cnt=0;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
//int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int w,int e)
{
    for(int i=0;i<4;i++)
    {
        int ww=w+dir[i][0];
        int ee=e+dir[i][1];
        //cout<<"ww* "<<ww<<"ee* "<<ee<<endl;
        if(mp[ww][ee]=='.'&&ww>=0&&ww<n&&ee>=0&&ee<m&&v[ww][ee]==0)
        {
            cnt++;
            v[ww][ee]=1;
            mp[ww][ee]='#';
           // cout<<"ww= "<<ww<<"ee= "<<ee<<endl;
            dfs(ww,ee);
        }
    }
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int x,y;
        memset(mp,0,sizeof(mp));
        memset(v,0,sizeof(v));
        if(m==0 ||n==0)
            break;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>mp[i][j];
                if(mp[i][j]=='@')
                {
                    x=i;
                    y=j;
                }
            }
        }
      // cout<<"x= "<<x<<"y= "<<y<<endl;
        mp[x][y]='#';
        v[x][y]=1;
        cnt=1;
        dfs(x,y);
        printf("%d\n",cnt);
    }
    return 0;
}

import turtle as t import random import time import os # 设置全局参数 CELL_SIZE = 40 # 单元格大小 GRID_WIDTH = 15 # 迷宫宽度(列数) GRID_HEIGHT = 10 # 迷宫高度(行数) HUNGER_THRESHOLD = 15 # 饥饿阈值(秒) FOOD_COUNT = 3 # 食物数量 MAX_SCORE = 5 # 触发特殊效果的分数 # 全局变量 score = 0 last_eat_time = time.time() maze_grid = [] foods = [] player = None score_turtle = None status_turtle = None instructions = None game_running = True # 初始化游戏 def init_game(): global player, score_turtle, status_turtle, instructions, maze_grid, foods, score # 创建屏幕 screen = t.Screen() screen.setup(1000, 800) screen.bgcolor("white") screen.title("海龟迷宫寻食游戏") screen.tracer(0) # 重置游戏状态 score = 0 last_eat_time = time.time() maze_grid = [] foods = [] # 创建玩家乌龟 player = t.Turtle() player.shape("turtle") player.color("blue") player.penup() player.speed(0) # 创建分数显示 score_turtle = t.Turtle() score_turtle.hideturtle() score_turtle.penup() score_turtle.goto(0, 350) score_turtle.color("black") # 创建状态显示 status_turtle = t.Turtle() status_turtle.hideturtle() status_turtle.penup() status_turtle.goto(0, 300) # 创建游戏说明 instructions = t.Turtle() instructions.hideturtle() instructions.penup() instructions.goto(0, -350) instructions.color("black") # 生成迷宫 generate_maze() # 放置食物 place_foods() # 设置键盘监听 screen.listen() screen.onkey(move_up, "Up") screen.onkey(move_down, "Down") screen.onkey(move_left, "Left") screen.onkey(move_right, "Right") screen.onkey(reset_game, "r") # 更新游戏状态 update_score() update_instructions() # 开始游戏循环 game_loop() # 递归分割算法生成迷宫 def generate_maze(): global maze_grid # 初始化迷宫网格 maze_grid = [[1 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)] # 设置入口和出口 maze_grid[0][0] = 0 # 入口 maze_grid[GRID_HEIGHT-1][GRID_WIDTH-1] = 0 # 出口 # 递归分割迷宫 def recursive_division(x, y, width, height): if width < 3 or height < 3: return # 随机选择分割方向 horizontal = width > height if width == height: horizontal = random.choice([True, False]) if horizontal: # 水平分割 split_y = random.randrange(y + 1, y + height - 1, 2) door_x = random.randrange(x, x + width, 2) for i in range(x, x + width): if i != door_x: maze_grid[split_y][i] = 1 recursive_division(x, y, width, split_y - y) recursive_division(x, split_y + 1, width, y + height - split_y - 1) else: # 垂直分割 split_x = random.randrange(x + 1, x + width - 1, 2) door_y = random.randrange(y, y + height, 2) for j in range(y, y + height): if j != door_y: maze_grid[j][split_x] = 1 recursive_division(x, y, split_x - x, height) recursive_division(split_x + 1, y, x + width - split_x - 1, height) # 生成迷宫结构 recursive_division(0, 0, GRID_WIDTH, GRID_HEIGHT) # 确保路径连通 ensure_path() # 绘制迷宫 draw_maze() # 确保从入口到出口有路径 def ensure_path(): # 使用深度优先搜索确保路径存在 visited = [[False for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)] stack = [(0, 0)] # 从入口开始 while stack: row, col = stack.pop() if row == GRID_HEIGHT - 1 and col == GRID_WIDTH - 1: # 到达出口 return True # 标记为已访问 visited[row][col] = True # 检查四个方向 directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右、下、左、上 for dr, dc in directions: new_row, new_col = row + dr, col + dc if (0 <= new_row < GRID_HEIGHT and 0 <= new_col < GRID_WIDTH and not visited[new_row][new_col] and maze_grid[new_row][new_col] == 0): # 通道 stack.append((new_row, new_col)) # 如果没有路径,创建一条 create_path() # 创建从入口到出口的路径 def create_path(): current_row, current_col = 0, 0 while current_row < GRID_HEIGHT - 1 or current_col < GRID_WIDTH - 1: # 优先向下或向右移动 if current_row < GRID_HEIGHT - 1 and random.random() > 0.3: current_row += 1 elif current_col < GRID_WIDTH - 1: current_col += 1 else: current_row += 1 maze_grid[current_row][current_col] = 0 # 设置为通道 # 绘制迷宫 def draw_maze(): t.clear() t.bgcolor("white") t.tracer(0) # 创建墙壁绘制器 wall_drawer = t.Turtle() wall_drawer.hideturtle() wall_drawer.penup() wall_drawer.speed(0) wall_drawer.pensize(3) wall_drawer.color("gray") # 绘制水平墙壁 for row in range(GRID_HEIGHT): for col in range(GRID_WIDTH): if maze_grid[row][col] == 1: # 墙 if col == 0 or maze_grid[row][col-1] == 0: wall_drawer.goto( (col - GRID_WIDTH // 2) * CELL_SIZE - CELL_SIZE // 2, (GRID_HEIGHT // 2 - row) * CELL_SIZE - CELL_SIZE // 2 ) wall_drawer.pendown() wall_drawer.goto( (col - GRID_WIDTH // 2 + 1) * CELL_SIZE - CELL_SIZE // 2, (GRID_HEIGHT // 2 - row) * CELL_SIZE - CELL_SIZE // 2 ) if col == GRID_WIDTH - 1 or maze_grid[row][col+1] == 0: wall_drawer.penup() # 绘制垂直墙壁 for col in range(GRID_WIDTH): for row in range(GRID_HEIGHT): if maze_grid[row][col] == 1: # 墙 if row == 0 or maze_grid[row-1][col] == 0: wall_drawer.goto( (col - GRID_WIDTH // 2) * CELL_SIZE - CELL_SIZE // 2, (GRID_HEIGHT // 2 - row) * CELL_SIZE - CELL_SIZE // 2 ) wall_drawer.pendown() wall_drawer.goto( (col - GRID_WIDTH // 2) * CELL_SIZE - CELL_SIZE // 2, (GRID_HEIGHT // 2 - row - 1) * CELL_SIZE - CELL_SIZE // 2 ) if row == GRID_HEIGHT - 1 or maze_grid[row+1][col] == 0: wall_drawer.penup() # 放置玩家在入口位置 player.goto( (0 - GRID_WIDTH // 2) * CELL_SIZE + CELL_SIZE // 2, (GRID_HEIGHT // 2 - 0) * CELL_SIZE - CELL_SIZE // 2 ) player.showturtle() # 放置食物 def place_foods(): global foods # 清除旧食物 for food in foods: food.clear() food.hideturtle() foods = [] # 创建新食物 for _ in range(FOOD_COUNT): food = t.Turtle() food.shape("circle") food.color("red") food.penup() food.speed(0) food.shapesize(0.8) # 随机放置食物(确保在通道上) while True: row = random.randint(0, GRID_HEIGHT - 1) col = random.randint(0, GRID_WIDTH - 1) # 确保不是墙,且不是入口/出口 if (maze_grid[row][col] == 0 and not (row == 0 and col == 0) and not (row == GRID_HEIGHT - 1 and col == GRID_WIDTH - 1)): break # 放置食物 food.goto( (col - GRID_WIDTH // 2) * CELL_SIZE + CELL_SIZE // 2, (GRID_HEIGHT // 2 - row) * CELL_SIZE - CELL_SIZE // 2 ) food.showturtle() foods.append(food) # 更新分数显示 def update_score(): score_turtle.clear() score_turtle.write(f"分数: {score}", align="center", font=("Arial", 20, "bold")) # 更新游戏说明 def update_instructions(): instructions.clear() instructions.write("方向键控制乌龟移动,寻找红色食物 | 按R重置游戏", align="center", font=("Arial", 14, "normal")) # 显示状态消息 def show_status(msg, color, duration=0): status_turtle.clear() status_turtle.color(color) status_turtle.write(msg, align="center", font=("Arial", 20, "bold")) if duration > 0: t.ontimer(lambda: status_turtle.clear(), int(duration * 1000)) # 检查碰撞 def check_collision(x, y): # 转换为网格坐标 col = int((x + (GRID_WIDTH * CELL_SIZE) / 2) // CELL_SIZE) row = int(((GRID_HEIGHT * CELL_SIZE) / 2 - y) // CELL_SIZE) # 检查边界 if col < 0 or col >= GRID_WIDTH or row < 0 or row >= GRID_HEIGHT: return True # 检查是否是墙 return maze_grid[row][col] == 1 # 检查食物碰撞 def check_food_collision(): global score, last_eat_time for food in foods[:]: px, py = player.position() fx, fy = food.position() if abs(px - fx) < CELL_SIZE/2 and abs(py - fy) < CELL_SIZE/2: # 吃到食物 food.hideturtle() foods.remove(food) score += 1 last_eat_time = time.time() update_score() # 分数为5分时的特殊效果 if score == MAX_SCORE: show_status("我吃饱了!", "green", 3.0) player.shapesize(2.0) player.color("dark blue") # 显示庆祝信息 celebration = t.Turtle() celebration.hideturtle() celebration.penup() celebration.goto(0, 0) celebration.color("gold") celebration.write("恭喜!你吃饱了!", align="center", font=("Arial", 24, "bold")) t.update() time.sleep(3) celebration.clear() else: show_status("我吃饱了!", "green", 2.0) # 如果食物吃完,重新放置 if not foods: place_foods() break # 检查饥饿状态 def check_hunger(): current_time = time.time() if current_time - last_eat_time > HUNGER_THRESHOLD: show_status("我饿了...", "red") else: status_turtle.clear() # 键盘控制函数 def move_up(): player.setheading(90) new_y = player.ycor() + CELL_SIZE//2 if not check_collision(player.xcor(), new_y): player.sety(new_y) check_food_collision() def move_down(): player.setheading(270) new_y = player.ycor() - CELL_SIZE//2 if not check_collision(player.xcor(), new_y): player.sety(new_y) check_food_collision() def move_left(): player.setheading(180) new_x = player.xcor() - CELL_SIZE//2 if not check_collision(new_x, player.ycor()): player.setx(new_x) check_food_collision() def move_right(): player.setheading(0) new_x = player.xcor() + CELL_SIZE//2 if not check_collision(new_x, player.ycor()): player.setx(new_x) check_food_collision() # 重置游戏 def reset_game(): global score, last_eat_time score = 0 last_eat_time = time.time() init_game() # 游戏主循环 def game_loop(): global game_running try: while game_running: t.update() time.sleep(0.01) # 定期检查饥饿状态 (每秒检查一次) if time.time() % 1 < 0.01: check_hunger() except t.Terminator: game_running = False # 启动游戏 if __name__ == "__main__": init_game() t.mainloop() 让迷宫变得超级复杂后的完整代码
最新发布
08-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值