POJ 1027 The Same Game(题解+代码)

题目传送门:http://poj.org/problem?id=1027
题目:

The Same Game

Description
The game named “Same” is a single person game played on a 10 \Theta 15 board. Each square contains a ball colored red ®, green (G), or blue (B). Two balls belong to the same cluster if they have the same color, and one can be reached from another by following balls of the same color in the four directions up, down, left, and right. At each step of the game, the player chooses a ball whose cluster has at least two balls and removes all balls in the cluster from the board. Then, the board is “compressed” in two steps:
1 . Shift the remaining balls in each column down to fill the empty spaces. The order of the balls in each column is preserved.
2 . If a column becomes empty, shift the remaining columns to the left as far as possible. The order of the columns is preserved.
For example, choosing the ball at the bottom left corner in the sub-board below causes:

POJ 1027 The Same Game

The objective of the game is to remove every ball from the board, and the game is over when every ball is removed or when every cluster has only one ball. The scoring of each game is as follows. The player starts with a score of 0. When a cluster of m balls is removed, the player’s score increases by ( m − 2 ) 2 (m-2)^2 (m2)2 . A bonus of 1000 is given if every ball is removed at the end of the game.
You suspect that a good strategy might be to choose the ball that gives the largest possible cluster at each step, and you want to test this strategy by writing a program to simulate games played using this strategy. If there are two or more balls to choose from, the program should choose the leftmost ball giving the largest cluster. If there is still a tie, it should choose the bottommost ball of these leftmost balls.
Input
You will be given a number of games in the input. The first line of input contains a positive integer giving the number of games to follow. The initial arrangement of the balls of each game is given one row at a time, from top to bottom. Each row contains 15 characters, each of which is one of “R”, “G”, or “B”, specifying the colors of the balls in the row from left to right. A blank line precedes each game.
Output
For each game, print the game number, followed by a new line, followed by information about each move, followed by the final score. Each move should be printed in the format:
Move x at (r,c): removed b balls of color C, got s points.
where x is the move number, r and c are the row number and column number of the chosen ball, respectively. The rows are numbered from 1 to 10 from the bottom, and columns are numbered from 1 to 15 from the left. b is the number of balls in the cluster removed. C is one of “R”, “G”, or “B”, indicating the color of the balls removed. s is the score for this move. The score does not include the 1000 point bonus if all the balls are removed after the move.
The final score should be reported as follows:
Final score: s, with b balls remaining.
Insert a blank line between the output of each game. Use the plural forms “balls” and “points” even if the corresponding value is 1.
Sample Input

3 
RGGBBGGRBRRGGBG 
RBGRBGRBGRBGRBG
RRRRGBBBRGGRBBB
GGRGBGGBRRGGGBG
GBGGRRRRRBGGRRR
BBBBBBBBBBBBBBB
BBBBBBBBBBBBBBB
RRRRRRRRRRRRRRR
RRRRRRGGGGRRRRR
GGGGGGGGGGGGGGG

RRRRRRRRRRRRRRR
RRRRRRRRRRRRRRR
GGGGGGGGGGGGGGG
GGGGGGGGGGGGGGG
BBBBBBBBBBBBBBB
BBBBBBBBBBBBBBB
RRRRRRRRRRRRRRR
RRRRRRRRRRRRRRR 
GGGGGGGGGGGGGGG
GGGGGGGGGGGGGGG

RBGRBGRBGRBGRBG
BGRBGRBGRBGRBGR
GRBGRBGRBGRBGRB
RBGRBGRBGRBGRBG
BGRBGRBGRBGRBGR
GRBGRBGRBGRBGRB
RBGRBGRBGRBGRBG
BGRBGRBGRBGRBGR
GRBGRBGRBGRBGRB
RBGRBGRBGRBGRBG

Sample Output

Game 1: 

Move 1 at (4,1): removed 32 balls of color B, got 900 points. 
Move 2 at (2,1): removed 39 balls of color R, got 1369 points. 
Move 3 at (1,1): removed 37 balls of color G, got 1225 points. 
Move 4 at (3,4): removed 11 balls of color B, got 81 points. 
Move 5 at (1,1): removed 8 balls of color R, got 36 points. 
Move 6 at (2,1): removed 6 balls of color G, got 16 points. 
Move 7 at (1,6): removed 6 balls of color B, got 16 points. 
Move 8 at (1,2): removed 5 balls of color R, got 9 points. 
Move 9 at (1,2): removed 5 balls of color G, got 9 points. 
Final score: 3661, with 1 balls remaining. 

Game 2: 

Move 1 at (1,1): removed 30 balls of color G, got 784 points. 
Move 2 at (1,1): removed 30 balls of color R, got 784 points. 
Move 3 at (1,1): removed 30 balls of color B, got 784 points. 
Move 4 at (1,1): removed 30 balls of color G, got 784 points. 
Move 5 at (1,1): removed 30 balls of color R, got 784 points. 
Final score: 4920, with 0 balls remaining. 

Game 3: 

Final score: 0, with 150 balls remaining.

题意:一个10*15的棋盘,每个格子里有红色,绿色或者蓝色的棋子。上下左右相邻的同色棋子组成一个棋簇(至少两个)。每个回合可以选择移走一个最大棋簇(有点类似于消灭星星),然后向下补其空格,再向左补其空格。
题解:用dfs找最大的棋簇(移除棋簇也可用dfs),bfs的话会mle,剩余的直接模拟即可
代码及注释如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char map[11][16],color;
int vis[11][16],maxx,x,y,num;
int nextt[4][2] = {1,0,0,1,-1,0,0,-1};
void dfs(int x, int y, char ch) {//计算棋簇大小
	for(int i = 0;i < 4;i++) {
		int tx = x + nextt[i][0];
		int ty = y + nextt[i][1];
		if(tx<1||tx>10||ty<0||ty>14) continue;//越界
		if(vis[tx][ty]||map[tx][ty]!=ch) continue;
		vis[tx][ty] = 1;//标记
		num++;//棋簇大小++
		dfs(tx,ty,ch);//ch为颜色
	}
}
void find_all() {//遍历整个棋盘,寻找最大棋簇
	memset(vis,0,sizeof(vis));//初始化标记数组
	for(int i = 0;i < 15;i++) {//先左(遍历列)
		for(int j = 1;j <= 10;j++) {//先下(遍历行)
			if(vis[j][i]||map[j][i]==' ') continue;
			vis[j][i] = num = 1;
			dfs(j,i,map[j][i]);//计算棋簇大小
			if(num>maxx) {
				maxx = num;//更新最大值
				x = j, y = i;//更新坐标
				color = map[x][y];//更新颜色
			}
		}
	}
}
int rest_num(int flag) {
	int rest = 0;
	for(int i = 1;i <= 10;i++) {
		for(int j = 0;j < 15;j++) {
			if(map[i][j] != ' ') {
				if(flag) rest++;//flag为1时,判断数量
				else return 1;//flag为0时,只判断是否为空
			}
		}
	}
	return rest;
}
void destroy(int x,int y) {//移出当前最大棋簇
	map[x][y] = ' ';//删除(每次递归到的都需要删除)
	for(int i = 0;i < 4;i++) {
		int tx = x + nextt[i][0];
		int ty = y + nextt[i][1];
		if(tx<1||tx>10||ty<0||ty>14) continue;//越界
		if(map[tx][ty] != color) continue;//不是指定颜色
		destroy(tx,ty);//递归
	}
}
void shift() {//调整棋盘
	char tmp[20];
	int cnt;
	//下降合并
	for(int i = 0;i < 15;i++) {//遍历列
		memset(tmp,0,sizeof(tmp));
		cnt = 1;//记录当前列还有多少个棋子
		for(int j = 1;j <= 10;j++) {//遍历行
			if(map[j][i] == ' ') continue;
			tmp[cnt++] = map[j][i];//保存非空字符数组
		}
		for(int j = 1;j < cnt;j++) map[j][i] = tmp[j];
		for(int j = cnt;j <= 10;j++) map[j][i] = ' ';
	}
	//靠左合并
	for(int i = 14;i >= 0;i--) {//遍历列
		int flag = 0;
		for(int j = 1;j <= 10;j++) {//判断是否为空列
			if(map[j][i] == ' ') continue;
			else flag = 1;
		}
		if(!flag) {//当前为空列
			for(int j = i;j <= 14;j++) {
				for(int k = 1;k <= 10;k++) {
					map[k][j] = map[k][j+1];//向左移
				}
			}
			for(int k = 1;k <= 10;k++) map[k][14] = ' ';//最右列清空
		}
	}
}
int main() {
	int t;
	scanf("%d",&t);
	for(int i = 1;i <= t;i++) {
		for(int j = 10;j >= 1;j--) {
			scanf("%s",map[j]);	//列起始点为0
		}
		if(i!=t) getchar();		//处理输入的空行
		printf("Game %d:\n\n",i);
		int cnt = 1,point = 0,sum = 0;
		while(rest_num(0)) {	//剩余数量不为0
			maxx = 1;
			find_all();			//寻找最大棋簇
			if(maxx==1) break;	//没有满足条件的棋簇
			destroy(x,y);		//清除最大棋簇
			shift();			//调整棋盘
			point = (maxx-2)*(maxx-2);//当前分数
			sum += point;		//总分数
			printf("Move %d at (%d,%d): removed %d balls",cnt++,x,y+1,maxx);
			printf(" of color %c, got %d points.\n",color,point);
		}
		int final = rest_num(1);//剩余数量
		if(!final) sum += 1000;	//全清空奖励1000
		printf("Final score: %d, with %d balls remaining.\n",sum,final);
		if(i!=t) printf("\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值