XDU Problem 1033 - 实验室的新机子

本文介绍了一种解决扫雷游戏问题的暴力搜索算法。通过分析五个已知位置及其周围格子的情况,利用2^16种可能性进行枚举验证,确保给定位置的布雷情况正确。该算法使用C++实现,详细展示了如何通过二进制枚举来找出所有可能的布雷方案。

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

扫雷啊,暴力搜索,给定五个位置,分析一下,最多只有16个周围的的格子,然后一一枚举就好了,2^16种,压力很小

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define col 30
using namespace std;
int dx[8]= {-1,-1,-1,0,0,1,1,1};
int dy[8]= {-1,0,1,-1,1,-1,0,1};
int map[16*30],s[20],vis[16*30],co[6],a,t;
int judge(int x,int y)   //判断x,y这个位置周围布雷情况是否符合
{
    int total=0;
    for(int i=0;i<8;i++)
    {
        int nx=x+dx[i],ny=y+dy[i],p=nx*col+ny,flag=1;

		for(int j=0;j<a;j++) if(p==co[j]) {flag=0;break;}
		if(!flag) continue;

        if(nx>=0&&nx<16&&ny>=0&&ny<30)
		total+=map[p];
    }
    if(total==map[x*col+y]) return 1;
    return 0;
}

int search()
{
    int N=(int)pow(2,t),flag=1,k=0,now[20]={0},ans=0,first=1;
	//cout<<N<<endl;
    for(int i=0;i<N;i++)        //利用二进制数枚举每种情况,分布在MAP数组中
    {
        int fg=1,d=i;
        for(int j=0;j<t;j++)
        {
            map[s[j]]=d&1;
            d/=2;
        }

        for(int j=0;j<a;j++) if(!judge(co[j]/col,co[j]%col)) {fg=0;break;}
        if(!fg) continue;   //如果给定的几个位置有一个不满足情况,继续循环

        flag=0;d=i;k=0;
        for(int j=0;j<t;j++)    //用vis记录布雷情况始终不变的位置
        {
            if(first)
            {
                vis[s[j]]=map[s[j]];
                first=0;
                //if(vis[s[j]]==1) ans++;
            }
            /*else if(map[s[j]]==vis[s[j]])
            {
                now[k++]=s[j];ans++;
            }*/
            else if((map[s[j]]==1&&vis[s[j]]==0)||(map[s[j]]==0&&vis[s[j]]==1))
            {
                vis[s[j]]=0;
            }

        }
        //return ans;
    }
    if(flag) return 0;
    for(int i=0;i<t;i++) if(vis[s[i]]==1) ans++;
    return ans;
}

int main()
{
    //freopen("data.txt","r",stdin);
    int T;
    cin>>T;
    while(T--)
    {
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        int x,y,num;
        cin>>a;
        t=0;
        for(int i=0; i<a; i++)
        {
            cin>>x>>y>>num;
            x-=1;y-=1;
            vis[x*col+y]=1;
			map[x*col+y]=num;
            co[i]=x*col+y;
        }
        for(int i=0;i<a;i++)
        {
            x=co[i]/col;
            y=co[i]%col;
            for(int j=0; j<8; j++)
            {
                int nx=x+dx[j],ny=y+dy[j],p=nx*col+ny;
                if(nx>=0&&nx<16&&ny>=0&&ny<30&&!vis[p]) {s[t++]=p;vis[p]=1;}
            }
        }
		//cout<<t<<endl;
        printf("%d\n",search());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值