题目:https://cn.vjudge.net/problem/UVA-758
题意:模拟一个游戏,棋盘大小10行15列,取左下角为原点建立坐标系,有三种棋子,题目给出一个初始状态。游戏初始得分为0。
要求进行以下三个阶段的操作:
(1)找到最大联通块,(若有多个优先选择最左的,若还有多个优先选择最下的),若联通块中棋子数>=2则清除,此时会得到(删除的棋子数 - 2)的平方的分数,依照要求输出。否则结束游戏。
(2)所有棋子垂直下落(如果下方有空格子)
(3)若有一整列空出来了,右方各列整体左移。
最终得分:若所有的棋子都被清空,则有1000分的奖励分。
最后输出最终得分和剩余棋子数。
思路:标准的搜索式大模拟,务必把各个功能模块分的足够清楚否则最后调试会疯的。
我是封装了两层结构体,把整个过程分成了,搜索并标记联通块、清除连通块、下落、左移四个部分。标记和清除用dfs完成的。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int maxn = 20;
int movex[] = { 0, 1, 0, -1 };
int movey[] = { 1, 0, -1, 0 };
struct Node
{
char c;
int num;
bool vis;
Node(char cc = 0) : c(cc), num(0), vis(false) {}
void clear()
{
*this = Node();
}
bool isblank()
{
return c == 0;
}
};
struct Board
{
Node node[maxn][maxn];
int index;
map<int, int> cntmap;
int score;
int amount;
int step;
Board()
{
init();
}
void init()
{
amount = 10 * 15;
index = 1;
step = 1;
cntmap.clear();
score = 0;
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
node[i][j].clear();
}
}
}
void clearboradvis()
{
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <= 15; j++)
{
node[i][j].vis = false;
}
}
}
void input()
{
char s[maxn] = { 0 };
for (int i = 1; i <= 10; i++)
{
scanf("%s", s + 1);
for (int j = 1; j <= 15; j++)
{
node[i][j] = Node(s[j]);
}
}
}
int mark()
{
int maxx = 0;
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <= 15; j++)
{
if (!node[i][j].isblank() && !node[i][j].vis)
{
dfs(i, j, index, node[i][j].c);
maxx = max(maxx, cntmap[index++]);
}
}
}
return maxx;
}
bool check(int x, int y)
{
return x >= 1 && x <= 10 && y >= 1 && y <= 15;
}
void dfs(int x, int y, int num, char c)
{
node[x][y].num = num;
node[x][y].vis = true;
cntmap[num]++;
for (int i = 0; i < 4; i++)
{
int newx = x + movex[i];
int newy = y + movey[i];
if (check(newx, newy) && !node[newx][newy].vis && node[newx][newy].c == c)
{
dfs(newx, newy, num, c);
}
}
}
void dfs(int x, int y, int num)
{
node[x][y].num = 0;
node[x][y].c = 0;
node[x][y].vis = true;
for (int i = 0; i < 4; i++)
{
int newx = x + movex[i];
int newy = y + movey[i];
if (check(newx, newy) && !node[newx][newy].vis && node[newx][newy].num == num)
{
dfs(newx, newy, num);
}
}
}
void clearmark()
{
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <= 15; j++)
{
node[i][j].num = 0;
node[i][j].vis = false;
}
}
index = 1;
cntmap.clear();
}
int getscore(int num)
{
return (num - 2) * (num - 2);
}
bool clearmaxcluster()
{
clearmark();
int maxcluster = mark();
if (maxcluster <= 1)
{
return false;
}
for (int j = 1; j <= 15; j++)
{
for (int i = 10; i >= 1; i--)
{
if (cntmap[node[i][j].num] == maxcluster)
{
printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n", step++, 10 - i + 1, j, cntmap[node[i][j].num], node[i][j].c, getscore(cntmap[node[i][j].num]));
clearboradvis();
score += getscore(cntmap[node[i][j].num]);
amount -= cntmap[node[i][j].num];
dfs(i, j, node[i][j].num);
return true;
}
}
}
return false;
}
void drop(int x, int y)
{
for (int i = x; i < 10; i++)
{
if (node[i + 1][y].isblank())
{
swap(node[i][y], node[i + 1][y]);
}
else
{
return;
}
}
}
void boarddrop()
{
for (int i = 10; i >= 1; i--)
{
for (int j = 1; j <= 15; j++)
{
if (!node[i][j].isblank())
{
drop(i, j);
}
}
}
}
bool isblankcolumn(int j)
{
for (int i = 10; i >= 1; i--)
{
if (!node[i][j].isblank())
{
return false;
}
}
return true;
}
void moveleft(int j)
{
for (int k = j; k >= 2; k--)
{
if (isblankcolumn(k - 1))
{
for (int i = 1; i <= 10; i++)
{
swap(node[i][k - 1], node[i][k]);
}
}
else
{
return;
}
}
}
void boardmoveleft()
{
for (int j = 1; j <= 15; j++)
{
moveleft(j);
}
}
};
Board board;
int main()
{
int T;
cin >> T;
for (int cases = 1; cases <= T; cases++)
{
if (cases != 1)
{
printf("\n");
}
board.init();
board.input();
printf("Game %d:\n\n", cases);
while (board.clearmaxcluster())
{
board.boarddrop();
board.boardmoveleft();
}
if (board.amount == 0)
{
printf("Final score: %d, with 0 balls remaining.\n", board.score + 1000);
}
else
{
printf("Final score: %d, with %d balls remaining.\n", board.score, board.amount);
}
}
return 0;
}