Gym101915E、Minesweeper (DFS)

                                                      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 
#include
#include
#include
#include
#include
#include
#include
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();
}

 

你可能感兴趣的:(Gym101915E、Minesweeper (DFS))