题目1 : 小Hi小Ho的惊天大作战:扫雷·三
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
于是问题来了:给出一张N*M(在经过三条规则的反复洗礼之后,N和M都并不会很大)的地图,其中的某些格子已经被探明,探明的格子中都标有一个数字,表明与它相邻的8个格子里的地雷数量,而没有探明的格子里可能会有一些地雷。
而现在小Ho需要做的便是:判断出这张地图中的哪些格子里一定是地雷,哪些格子里一定不是地雷。(在多解情况下,一定是地雷以及一定不是地雷的定义指的是在每一种可行解中都是地雷或者都不是地雷)
输入
每个测试点(输入文件)存在多组测试数据。
每个测试点的第一行为一个整数Task,表示测试数据的组数。
在一组测试数据中:
第1行为2个整数N,M,表示迷宫的大小。
接下来的N行,每行M个整数,为一个矩阵A,用以描述整个迷宫,其中对于每一个格子A[i][j],若A[i][j]=-1,则表示该格子没有被探明,若0<=a[i][j]<=8,则表示该格子已经被探明了,且数值代表该格子附近8个格子中的地雷数。<>
对于100%的数据,满足:5<=N、M<=10, -1<=a[i][j]<=8。<>
对于100%的数据,满足:符合数据描述的迷宫一定存在。
对于100%的数据,满足:迷宫中没有探明的格子的数量K<=10。<>
输出
对于每组测试数据,输出2个整数,分别为一定为地雷的未探明格子数和一定不为地雷的未探明格子数。
样例输入
2 10 10 0 0 1 2 -1 1 0 0 1 -1 1 1 1 -1 2 1 0 0 1 1 -1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 -1 1 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 -1 1 0 -1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 -1 0 0 -1 1 -1 1 0 0 0 9 10 0 0 0 0 0 -1 0 0 -1 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 2 3 -1 1 0 0 0 0 -1 1 -1 -1 3 1 1 1 0 0 0 1 3 -1 2 0 -1 1 0 0 0 0 1 1 -1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
样例输出
7 3 5 5
解题思路:直接爆搜。
复杂度2^k*m*n;
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
int n,m;
int a[20][20],b[20][20];
int vis[20][20],vis1[20][20];
int dx[10]= {0,1,1,1,0,-1,-1,-1};
int dy[10]= {1,1,0,-1,-1,-1,0,1};
typedef pair<int,int>pii;
vector<pii>v;
int k;
int cal(int x,int y)
{
int ans=0;
for(int i=0;i<8 ;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1||xx>n||yy<1||yy>m)continue;
if(a[xx][yy]==-2)ans++;
}
return ans;
}
bool judge( )
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]>=0)
{
int tmp=cal(i,j);
if(a[i][j]!=tmp)return false;
}
}
}
return true;
}
void dfs(int now)
{
if(now==k)
{
if(!judge()) return ;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==-2)vis[i][j]++;
if(a[i][j]==-3)vis1[i][j]++;
}
}
return ;
}
int tx=v[now].first;
int ty=v[now].second;
a[tx][ty]=-2;
dfs(now+1);
a[tx][ty]=-3;
dfs(now+1);
a[tx][ty]=-1;
}
int main()
{
int t;
sca(t);
//freopen("D:\ou.txt","w",stdout);
while(t--)
{
sca(n),sca(m);
k=0;
v.clear();
memset(vis,0,sizeof(vis));
memset(vis1,0,sizeof(vis1));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
sca(a[i][j]);
if(a[i][j]==-1)k++,v.pb(mp(i,j));
}
}
dfs(0);
int ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(vis[i][j]==0&&vis1[i][j]!=0)ans1++;
if(vis[i][j]!=0&&vis1[i][j]==0)ans2++;
}
}
cout<<ans2<<" "<<ans1<<endl;
}
}