题目大意:
在一个10x15的方阵里填满了RGB三种小球,要求:
1、找到最大的一片相同颜色区域,并删掉,(这片区域相同颜色球必须相邻,且相邻数大于1)。
2、删除完成后,其他小球自然下落填充。先每列向下填充,空的列由右边一列平移补全。
3、当区域内没有球或最大相邻区域的个数为一,游戏结束。
题解:
主函数如下
while (true){ int num = getAllMarked(); if (num <= 1)break; getMaxMark(num, ++step); format(); }
其中,getAllMarked从左下角向右上进行深度优先遍历,刷新num值(相同颜色区域大小)
getMaxMark从左下向右上找到连通数为num的点集,并将其标记为‘X’。
注意点:
1. 进行遍历所使用的vis数组
vis[i][j] = mark(i, j, data[i][j]);
该数组当且仅当getAllMarked函数进入时进行初始化,作为地图使用
2. format函数类似于STL库中的unique函数,从左(col = 0)下(row=MAXR - 1)开始,遍历
data[row][col] = data[row - offset][col + blank];
format函数实现如下
void format(){ int col, row, blank = 0, offset; for (col = 0; col + blank < MAXC; ){ //用blank记录空行的个数 offset = 0; //每列维护一个offset偏移量 for (row = MAXR - 1; row - offset >= 0; ){ //循环结束row或offset变化 if (data[row - offset][col + blank] == 'X')++offset; //跳过 else{ data[row][col] = data[row - offset][col + blank]; --row; } } if (offset == MAXR)++blank; //没有执行赋值操作,该列为空列 else{ for (int i = row; i >= 0; --i)data[i][col] = 'X'; ++col; //将要被删除的点赋值,为下次查找排除干扰 } } for (int j = col; j < MAXC; ++j) for (int i = 0; i < MAXR; ++i) data[i][j] = 'X'; //将空行赋值 }
本题目的完整代码如下,仅供初学者参考
/* POJ 1027 - Same Game 题目大意: 在一个10x15的方阵里填满了RGB三种小球,要求: 1、找到最大的一片相同颜色区域,并删掉,(这片区域相同颜色球必须相邻,且相邻数大于1)。 2、删除完成后,其他小球自然下落填充。先每列向下填充,空的列由右边一列平移补全。 3、当区域内没有球或最大相邻区域的个数为一,游戏结束。 */ #include <stdio.h> #define MAXC 15 #define MAXR 10 #define ONLINE_JUDGE int T, N, M, ans, res, next; char data[MAXR][MAXC]; int vis[MAXR][MAXC]; int dy[] = { 0, 1, 0, -1 }; int dx[] = { 1, 0, -1, 0 }; int mark(int y, int x, char color){ int num = 1; for (int i = 0; i < 4; ++i){ int ny = y + dy[i], nx = x + dx[i]; if (ny >= 0 && ny < MAXR && nx >= 0 && nx < MAXC && (data[ny][nx] == color) && vis[ny][nx] < 0){ vis[ny][nx] = 0; num += mark(ny, nx, color); } } return num; } int getAllMarked(){ for (int i = 0; i < MAXR; ++i) for (int j = 0; j < MAXC; ++j) vis[i][j] = -1; int num = 0; for (int j = 0; j < MAXC; ++j) for (int i = MAXR - 1; i >= 0; --i){ if (vis[i][j] < 0 && data[i][j] != 'X'){ vis[i][j] = 0; vis[i][j] = mark(i, j, data[i][j]); if (vis[i][j] > num)num = vis[i][j]; } } return num; } void markX(int y, int x, char color){ data[y][x] = 'X'; for (int i = 0; i < 4; ++i){ int ny = y + dy[i], nx = x + dx[i]; if (ny >= 0 && ny < MAXR && nx >= 0 && nx < MAXC && (data[ny][nx] == color)){ markX(ny, nx, color); } } } void getMaxMark(int num, int step){ for (int j = 0; j < MAXC; ++j) for (int i = MAXR - 1; i >= 0; --i){ if (vis[i][j] == num){ int offset = (num - 2)*(num - 2); printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n", step, MAXR - i, j + 1, num, data[i][j], offset); res -= num; ans += offset; markX(i, j, data[i][j]); return; } } } void format(){ int col, row, blank = 0, offset; for (col = 0; col + blank < MAXC; ){ offset = 0; for (row = MAXR - 1; row - offset >= 0; ){ if (data[row - offset][col + blank] == 'X')++offset; else{ data[row][col] = data[row - offset][col + blank]; --row; } } if (offset == MAXR) ++blank; else{ for (int i = row; i >= 0; --i){ data[i][col] = 'X'; } ++col; } } for (int j = col; j < MAXC; ++j) for (int i = 0; i < MAXR; ++i) data[i][j] = 'X'; } int main(){ #ifndef ONLINE_JUDGE freopen("sample_input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif scanf("%d", &T); for (int tc = 1; tc <= T; ++tc){ printf("Game %d:\n\n", tc); for (int i = 0; i < MAXR; ++i) scanf("%s", &data[i]); res = 150; ans = 0; int step = 0; while (true){ int num = getAllMarked(); if (num <= 1)break; getMaxMark(num, ++step); format(); } if (res == 0)ans += 1000; printf("Final score: %d, with %d balls remaining. \n\n", ans, res); } }