首页 > 技术文章 > 练习题(模拟) Same Game POJ1027 消除游戏

proscientist 2018-02-24 15:11 原文

题目大意:
在一个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);
	}
}

 

推荐阅读