1 条题解
-
0
中文翻译
题目名称: Flood-it 游戏
题目描述:
Flood-it 是 Google+ 平台上一款有趣的益智游戏。游戏界面如下:
游戏开始时,系统会随机生成一个 的方形棋盘,棋盘的每个格子被涂成六种颜色之一。玩家从棋盘的左上角开始。每一步,玩家选择一种颜色,并将与左上角相连的所有格子更改为该颜色。这里的“两个格子相连”指的是这两个格子之间存在一条路径,该路径上的每一对相邻格子颜色相同且共享一条边。通过这种方式,玩家可以从起始格子(左上角)开始“淹没”棋盘区域,直到所有格子都变为同一种颜色。下图展示了一个 游戏的最初几步(颜色用 到 标记):
给定初始棋盘的颜色分布,请找出赢得游戏(将所有格子变为同一种颜色)所需的最少步数。
输入格式:
输入包含不超过 个测试用例。每个测试用例的第一行包含一个整数 (),表示棋盘的大小。接下来的 行展示一个 的矩阵 ,表示棋盘。 的取值范围是 到 ,表示对应格子的颜色。输入以 结束。
输出格式:
对于每个测试用例,输出一个整数,表示赢得游戏所需的最少步数。
样例输入 1:
2 0 0 0 0 3 0 1 2 1 1 2 2 2 1 0
样例输出 1:
0 3
题意分析
Flood-it 游戏的目标是通过最少的步数将整个棋盘的所有格子变为同一种颜色。每一步操作是:选择一种颜色,将与当前左上角连通区域相邻的同色格子“淹没”(即合并到连通区域中)。连通区域的定义是通过相邻(上下左右)的同色格子可以到达的区域。
解题思路
-
问题建模:这是一个典型的状态空间搜索问题,可以使用广度优先搜索(BFS)或启发式搜索(如 A* 算法)来解决。由于棋盘大小 最大为 ,状态空间可能较大,需要优化。
-
状态表示:每个状态可以表示为当前棋盘的颜色分布和当前的连通区域。为了高效表示状态,可以用一个二维数组表示棋盘,并用一个标记数组记录当前的连通区域。
-
BFS 策略:
- 初始状态:棋盘的初始颜色分布,连通区域为左上角的格子及其同色连通区域。
- 每次操作:从当前连通区域的相邻格子中选择一种颜色,扩展连通区域。
- 目标状态:所有格子颜色相同。
-
优化:
- 使用哈希表记录已访问的状态,避免重复搜索。
- 每次扩展时,只考虑与当前连通区域相邻的颜色。
-
剪枝:可以通过估计剩余步数的启发式函数进行剪枝,比如当前连通区域未覆盖的颜色种类数。
C++代码
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; const int dx[4] = {0,0,-1,1}; const int dy[4] = {-1,1,0,0}; int i,j,n,step; int v[10][10],a[10][10]; inline bool valid(int x,int y) { return x > 0 && x <= n && y > 0 && y <= n; } inline void dfs(int x,int y,int c) { int i,tx,ty; v[x][y] = 1; for (i = 0; i < 4; i++) { tx = x + dx[i]; ty = y + dy[i]; if (valid(tx,ty) && v[tx][ty] != 1) { if (a[tx][ty] == c) dfs(tx,ty,c); else v[tx][ty] = 2; } } } inline int f() { int i,j,s = 0; bool h[10]; memset(h,0,sizeof(h)); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (!h[a[i][j]] && v[i][j] != 1) { h[a[i][j]] = true; s++; } } } return s; } inline bool fill(int c) { int i,j,s = 0; for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (a[i][j] == c && v[i][j] == 2) { s++; dfs(i,j,c); } } } return s != 0; } inline bool IDDFS(int dep) { int i,t; int tmp[10][10]; t = f(); if (dep + t > step) return false; if (!t) return true; for (i = 0; i <= 5; i++) { memcpy(tmp,v,sizeof(v)); if (fill(i) && IDDFS(dep+1)) return true; memcpy(v,tmp,sizeof(v)); } return false; } int main() { while (scanf("%d",&n) != EOF && n) { memset(v,0,sizeof(v)); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { scanf("%d",&a[i][j]); } } dfs(1,1,a[1][1]); for (i = 0; i <= n * n; i++) { step = i; if (IDDFS(0)) break; } printf("%d\n",step); } return 0; }
-
- 1
信息
- ID
- 2987
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者