Minesweeper
Have you ever played Minesweeper? It’s a cute little game that originates from the 1960s, and has been written for many computing platforms in use today.
The game consists of a two dimensional grid, and there are two types of cells in it.
A mined cell, and an empty cell, which contains a single digit that indicates how many adjacent cells contain mines. Eech cell has at most 8 adjacent cells.
In this version of the game, you are going to build a level with the following rules:
- Every mined cell has to be a neighbor of at least one empty cell.
- Every empty cell can have at most M adjacent mines.
For instance, the following is 4 * 5 valid grid with 12 mines (which are represented by an '*' character) and the maximum number for the empty cells is M = 3 :
3 * * 3 1
* * * * 2
* * * * 2
3 * * 3 1
We are interested in the maximum number of mines that a grid with those properties can contain, can you find the answer for us?
Input
The first line contains a single integer T denoting the number of test cases.
Each test case consists of one line which contains three space separated integers:
The number of the rows in the grid r. (2 ≤ r ≤ 6).
The number of the columns in the grid c. (2 ≤ c ≤ 6).
The maximum number that any empty cell can contain. (1 ≤ M ≤ 8).
Output
For each test print one line containing one integer, the maximum number of mines that a grid can contain.
Example
Input
2
4 5 3
3 3 4
Output
12
6
Note
The grid in the statement is a valid grid for the first sample.
一、原题地址
二、大致题意
扫雷游戏,给定的是n*m大小的棋盘,还有其中能存在的最大数字K。规定在一个3*3的格子里元素不能全部是雷。
询问在符合规定的情况下,雷最多能放多少个。
三、思路
每个格子可以是雷也可以是数字,所以可以枚举(一开始我是打算枚举全部的数字,9个出口果然超时)每个格子是雷还是数字。对于雷我们先放置1,我们的check应该是检查他的周围有没有存在数字,而对于数字我们先放置0,然后需要check他的周围雷的数量会不会超过K个,这样的检查可以保证一个棋盘是一定符合状态的,但是这并不一定是我们所求的。但是随着DFS的深入,更新的是一定会慢慢增大,直到找到我们需要的答案。
对于一个格子(x,y)该放置什么,我们检索他的右上角(x-1,y-1)能否符合情况雷或者数字的情况。但对于最后一行和最右边的一列,我们还需要分别检索(x,y-1)和(x-1,y),只要画一张图就很好理解了。
看到时间限制是15秒,本来以为还需要先打表将答案记录下来。但是交了两发最后还是发现直接读取n,m,K会快两倍。说明T的数据范围并不是很大。
四、代码
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long int INF = 1e18;
typedef long long LL;
int T;
int n, m, K, ans;
int mmp[10][10];
int x[] = { 1,1,1,0,0,-1,-1,-1 };
int y[] = { 1,0,-1,1,-1,1,0,-1 };
bool check(int nn, int mm)
{
if (mmp[nn][mm] == inf)return true;
if (mmp[nn][mm])
{
for (int i = 0; i < 8; i++)
{
int xx = nn + x[i], yy = mm + y[i];
if (xx >= 1 && xx <= n&&yy >= 1 && yy <= m)
{
if (!mmp[xx][yy])return true;
}
}
return false;
}
else
{
int cnt = 0;
for (int i = 0; i < 8; i++)
{
int xx = nn + x[i], yy = mm + y[i];
if (xx >= 1 && xx <= n&&yy >= 1 && yy <= m)
{
if (mmp[xx][yy])cnt++;
}
}
if (cnt > K )return false;
return true;
}
}
void print()
{
printf("--------------------------------------\n");
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
printf("%d", mmp[i][j]);
}
printf("\n");
}
}
void DFS(int nx, int ny, int now, int last)
{
if (now + last <= ans)return;
if (nx>n)
{
if (check(n, m) && check(n - 1, m))
{
ans = max(ans, now);
//print();
}
return;
}
for (int i = 0; i <= 1; i++)
{
mmp[nx][ny] = i;
//print();
if (nx == n)
{
if (check(nx - 1, ny - 1) && check(nx, ny - 1))
{
if (ny == m&&check(nx - 1, m))DFS(nx + 1, 1, now + i, last - 1);
else DFS(nx, ny + 1, now + i, last - 1);
}
}
else if (ny == m)
{
if (check(nx - 1, ny - 1) && check(nx - 1, ny))
{
DFS(nx + 1, 1, now + i, last - 1);
}
}
else if (check(nx - 1, ny - 1))
{
DFS(nx, ny + 1, now + i, last - 1);
}
}
return;
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d %d %d", &n, &m, &K);
memset(mmp, inf, sizeof(mmp));
ans = 0;
DFS(1, 1, 0, n*m);
printf("%d\n", ans);
}
getchar();
getchar();
}