hiho 小Hi小Ho的惊天大作战:扫雷·一 扫雷·三

题目链接:

扫雷1

扫雷3


扫雷2并不科学(见扫雷3里的第一个提示,)然后就没写了- -





思路:


扫雷一:

只有一行

枚举第一个格子为有雷 或者 没有雷

然后再往下搜索 得到多个可行解

所有可行解的某个位置都为雷的一定为雷

所有可行解的某个位置都不为为雷的一定为不为雷


扫雷三:思路1:未知的位置只有不超过10个,直接爆力枚举所有未知的位置

得到多个可行解

所有可行解的某个位置都为雷的一定为雷

所有可行解的某个位置都不为为雷的一定为不为雷


思路2:根据条件1:.如果某一个被探明的格子里所标的数字为0,那么它相邻的8个格子里的未探明格子被认作是一定不是地雷的格子

和条件2:如果某一个被探明的格子里所标的数字为K,且它相邻的8个格子里正好有K个没有探明的格子的话,则这K个没有探明的格子被认作是一定是地雷的格子

反复处理 可以得出全部完整的地图(输出答案)

   一副部分完整的地图

然后再  搜索枚举所有未知的位置为有雷或者没有雷

得到多个可行解

所有可行解的某个位置都为雷的一定为雷

所有可行解的某个位置都不为为雷的一定为不为雷






扫雷1代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100050
using namespace std;
int ans[105][maxn];
int mine[maxn];
int ans1[maxn],ans2[maxn];
int d[maxn];
int n;
int s;
void dfs(int loc)
{
    if(loc==n+1)
    {
        if(mine[loc-1]==d[loc-2]+d[loc-1])
        {
            s++;
            for(int i=1; i<=n; i++)
                ans[s][i]=d[i];
        }
        return;
    }
    if(mine[loc-1]==d[loc-2]+d[loc-1])
    {
        d[loc]=0;
        dfs(loc+1);
    }
    else if(mine[loc-1]==d[loc-2]+d[loc-1]+1)
    {
        d[loc]=1;
        dfs(loc+1);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        s=0;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&mine[i]);
        d[0]=d[1]=0;
        dfs(2);
        d[0]=0;
        d[1]=1;
        dfs(2);
        int s1=0,s2=0;
        if(s==1)
        {
            for(int j=1;j<=n;j++)
            {
                if(ans[1][j]==0)
                    ans1[s1++]=j;
                else
                    ans2[s2++]=j;
            }
        }
        else
        {
            for(int j=1;j<=n;j++)
            {
                if(ans[1][j]==0&&ans[2][j]==0)
                    ans1[s1++]=j;
                else if(ans[1][j]==1&&ans[2][j]==1)
                    ans2[s2++]=j;
            }
        }
        printf("%d",s2);
        for(int i=0;i<s2;i++)
            printf(" %d",ans2[i]);
        cout<<endl;
        printf("%d",s1);
        for(int i=0;i<s1;i++)
            printf(" %d",ans1[i]);
        cout<<endl;
    }
    return 0;
}



扫雷3代码1:

#include<cstdio>
//-2no -3yes
int s[12][12];
int a[10][2];
int f[10];
int n,m,le;
int remain[12][12];

bool check(int k)
{
	int i,j,sum;
	int x=a[k][0];
	int y=a[k][1];
	for(i=0;i<9;i++)
		if(remain[x+i/3-1][y+i%3-1]==0)
			return false;
	return true;
}

void work(int k)
{
	int i,j;
	int x=a[k][0];
	int y=a[k][1];
	if(k<le)
	{
		if(check(k))
		{
			s[x][y]=-3;
			for(i=0;i<9;i++)
				if(remain[x+i/3-1][y+i%3-1]>0)
					remain[x+i/3-1][y+i%3-1]--;
			work(k+1);
			for(i=0;i<9;i++)
				if(remain[x+i/3-1][y+i%3-1]>=0)
					remain[x+i/3-1][y+i%3-1]++;
		}
		s[x][y]=-2;
		work(k+1);
	}
	else 
	{
		for(i=0;i<le;i++)
			for(j=0;j<9;j++)
				if(remain[a[i][0]+j/3-1][a[i][1]+j%3-1]>0)
					return;
		for(i=0;i<le;i++)
			if(f[i]==0)
				f[i]=s[a[i][0]][a[i][1]];
			else if(f[i]!=s[a[i][0]][a[i][1]])
				f[i]=-1;
	}
}

int main(){
	int i,j,t,ans1,ans2;
	scanf("%d",&t);
	while(t--){
		le=0;
		scanf("%d%d",&n,&m);
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
			{
				scanf("%d",&s[i][j]);
				if(s[i][j]==-1)
				{
					a[le][0]=i;
					a[le][1]=j;
					le++;
				}
			}
		for(i=0;i<=n+1;i++){
			s[i][0]=-2;
			s[i][m+1]=-2;
		}
		for(j=0;j<=n+1;j++){
			s[0][j]=-2;
			s[n+1][j]=-2;
		}
		for(i=0;i<le;i++)
			f[i]=0;
		for(i=0;i<=n+1;i++)
			for(j=0;j<=m+1;j++)
				remain[i][j]=s[i][j];
		work(0);
		ans1=0;ans2=0;
		for(i=0;i<le;i++)
			if(f[i]==-3)
				ans1++;
			else if(f[i]==-2)
				ans2++;
		printf("%d %d\n",ans1,ans2);
	}
	return 0;
}

扫雷3代码2:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 210
using namespace std;
struct node
{
    int x,y,d;
};
queue<node>q;
int map[maxn][maxn];
int remain[maxn][maxn];
int n_know[maxn][maxn];
int possible[maxn][2],possible_num;
int dir[8][2]= {1,0,-1,0,0,1,0,-1, 1,1,1,-1,-1,1,-1,-1};
int n,m;
int ans1,ans2;
int no_know;

int f[maxn];

void update(int x,int y,int d)       //更新remain 如果满足条件一二则继续处理
{
    int tx,ty;
    for(int i=0; i<8; i++)
    {
        tx=x+dir[i][0];
        ty=y+dir[i][1];
        if(x<1||y<1||x>n||y>m)
            continue;
        if(map[tx][ty]>=1&&map[tx][ty]<=8&&d==0)
        {
            n_know[tx][ty]--;
            if(n_know[tx][ty]==remain[tx][ty])
                q.push( {tx,ty,map[tx][ty]});
        }
        if(map[tx][ty]>=1&&map[tx][ty]<=8&&d==1)
        {
            remain[tx][ty]--;
            n_know[tx][ty]--;
            if(remain[tx][ty]==0)
                q.push( {tx,ty,0});
        }
    }
}


int judge(int x,int y,int d)   //d=-1:统计n_know  0:条件1  1~8:条件2
{
    int tx,ty,s=0;
    for(int i=0; i<8; i++)
    {
        tx=x+dir[i][0];
        ty=y+dir[i][1];
        if(x<1||y<1||x>n||y>m)
            continue;
        if(map[tx][ty]==-1&&d==-1)
            s++;

        if(map[tx][ty]==-1&&d==0)
        {
            map[tx][ty]=10;
            ans1++;
            no_know--;
            update(tx,ty,0);
        }

        if(map[tx][ty]==-1&&d>=1&&d<=8)
        {
            map[tx][ty]=-2;
            ans2++;
            no_know--;
            update(tx,ty,1);
        }
    }
    if(d==-1)
        return s;

}

bool check(int k)
{
    int x=possible[k][0];
    int y=possible[k][1];
    for(int i=0; i<9; i++)
        if(remain[x+i/3-1][y+i%3-1]==0)
            return false;
    return true;
}

void dfs(int loc)
{
    int x=possible[loc][0];
    int y=possible[loc][1];
    if(loc<possible_num)
    {
        if(check(loc))
        {
            map[x][y]=-2;
            for(int i=0; i<9; i++)
                if(remain[x+i/3-1][y+i%3-1]>0)
                    remain[x+i/3-1][y+i%3-1]--;
            dfs(loc+1);
            for(int i=0; i<9; i++)
                if(remain[x+i/3-1][y+i%3-1]>=0)
                    remain[x+i/3-1][y+i%3-1]++;
        }
        map[x][y]=10;
        dfs(loc+1);
    }
    else
    {
        for(int i=0; i<possible_num; i++)
            for(int j=0; j<9; j++)
                if(remain[possible[i][0]+j/3-1][possible[i][1]+j%3-1]>0)
                    return;
        for(int i=0; i<possible_num; i++)
            if(f[i]==0)
                f[i]=map[possible[i][0]][possible[i][1]];
            else if(f[i]!=map[possible[i][0]][possible[i][1]])
                f[i]=-1;
    }
}


void work()
{
    node head;
    while(!q.empty())
    {
        head=q.front();
        q.pop();
        judge(head.x,head.y,head.d);
    }

    if(no_know==0)
        cout<<ans2<<" "<<ans1<<endl;
    else             //地图未完整
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                if(map[i][j]==-1)
                    possible[possible_num][0]=i,possible[possible_num++][1]=j;

        dfs(0);

        for(int i=0; i<possible_num; i++)
            if(f[i]==10)
                ans1++;
            else if(f[i]==-2)
                ans2++;

        cout<<ans2<<" "<<ans1<<endl;
//        for(int i=1;i<=n;i++){
//            for(int j=1;j<=m;j++)
//            printf("%4d",map[i][j]);
//            cout<<endl;
//        }
    }
}



void init()
{
    memset(f,0,sizeof(f));
    while(!q.empty())
        q.pop();
    ans1=ans2=0;
    no_know=0;
    possible_num=0;
    for(int i=0; i<=n+1; i++)
    {
        map[i][0]=10;
        map[i][m+1]=10;
    }
    for(int j=0; j<=n+1; j++)
    {
        map[0][j]=10;
        map[n+1][j]=10;
    }
}



int main()
{
    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                scanf("%d",&map[i][j]);
                remain[i][j]=map[i][j];
                if(map[i][j]==-1)
                    no_know++;
            }
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                n_know[i][j]=judge(i,j,-1);
                if(remain[i][j]==0||remain[i][j]==n_know[i][j])
                    q.push({i,j,map[i][j]});
            }
        work();
    }
    return 0;
}
//我简直是有强迫症..... 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值