SDUT 2410 Mine Number DFS+回溯 (扫雷)

本文介绍了一种使用深度优先搜索(DFS)算法解决雷区问题的方法。通过枚举和判断周围的数字来决定是否放置地雷,并进行相应的操作。算法在每一步中都考虑了边界条件和状态转移,确保了问题的有效解决。

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

点击打开链接

DFS,深度优先搜索。

大体的思路方向是:

从0,0开始往后判断,每个点是否放雷,依据就是周围的数字(上下左右)是否有0的情况,有0就不放雷。

放雷后就要将五个方向的数字减1,然后继续往后判断。

这是主要的判断,但是显然需要大的前提来 剪掉大半棵树。

→首先将第一行枚举,然后每一行根据上一行状态来做:

如果上一行同位置数字为0,则该点不放雷。

如果上一行同位置数字为1,则该点必须放雷,此时判断四周是否有0的情况,没有则放雷,有则回溯。

如果上一行同位置数字不为0或者1,则回溯。

判断到最后一行,需要将最后一行数组判断,是否全为0,是则输出结果,不是则回溯。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
#define mod 1000000007
using namespace std;
#define N 1001
char s[100][100];
int a[100][100];
char c[100][100];
char Map[100][100];
int n,m;
int dx[]= {-1,1,0,0,0};
int dy[]= {0,0,0,-1,1};
///判断边界
int judge(int x,int y)
{
    if(x<0||y<0||x>=n||y>=m)
        return 0;
    return 1;
}
///判断周围的5处地方 是否存在 小于等于0 的情况
int solve(int x,int y)
{
    for(int i=0; i<5; i++)
    {
        int fx=dx[i]+x;
        int fy=dy[i]+y;
        if(judge(fx,fy)&&a[fx][fy]<=0) return 0;
    }
    return 1;
}
///对周围的5处的 *的个数 进行操作 +1 或 -1
void change(int x,int y,int c)
{
    for(int i=0; i<5; i++)
    {
        int fx=dx[i]+x;
        int fy=dy[i]+y;
        if(judge(fx,fy))
            a[fx][fy]=a[fx][fy]+c;
    }
}
int flag=0;
int DFS(int x,int y)
{
    if(flag)             ///找到了满足条件的
        return 0;
    if(x==n)
    {
        int f=0;
        for(int i=0; i<m; i++)   ///判断最后一行的a[][] 是否全为0
            if(a[n-1][i])
            {
                f=1;
                break;
            }
        if(!f)
        {
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                    printf("%c",Map[i][j]);
                printf("\n");
            }
            flag=1;
        }
        return 0;
    }
    if(y==m)
    {
        DFS(x+1,0); ///return 0;
    }
    else if(x==0)
    {
        if(solve(x,y))    ///周围有*的个数为0 的情况所以 此处为 '.'
        {
            Map[x][y]='*';
            change(x,y,-1);
            DFS(x,y+1);
            change(x,y,+1);
        }
        ///1周围有*的个数为0 的情况所以 此处为 '.'    或者2 是回溯后的情况
         Map[x][y]='.';
         DFS(x,y+1);
    }
    else
    {
        if(a[x-1][y]==0)  ///上一层为0 下一层一定为 ‘.’ 
        {
            Map[x][y]='.';
            DFS(x,y+1);
        }
        else if(a[x-1][y]==1)  ///上一层为1 该层一定为 ‘*’;
        {
            if(solve(x,y))
            {
                Map[x][y]='*';
                change(x,y,-1);
                DFS(x,y+1);
                change(x,y,1);
            }
        }
    }
}
int main()
{
    int T;
    while(~scanf("%d",&T))
    {
        for(int cas=1; cas<=T; cas++)
        {
            ///  memset(vis,0,sizeof(vis));
            scanf("%d%d",&n,&m);
            for(int i=0; i<n; i++)
            {
                scanf("%s",s[i]);
                for(int j=0; j<m; j++)
                    a[i][j]=s[i][j]-'0';
            }
            flag=0;
            printf("Case %d:\n",cas);
            DFS(0,0);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值