The Same Game POJ

来源:互联网 发布:火箭 模拟软件 编辑:程序博客网 时间:2024/06/05 09:44

The game named “Same” is a single person game played on a 10 \Theta 15 board. Each square contains a ball colored red (R), 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:
这里写图片描述
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 . 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的区域,被RGB(红绿蓝)三种颜色的小球充满。要求 每次找出当前最大连通区域(上下左右相邻同种颜色即可算作连 通),进行消除。消除后空白区域由该列上方格子自由下落进行 填补。如果出现某列全部清空的情况,将其逐列右移,直至遇到空列。然后开始你的分数为0,每次消除m个球后你的分数会增加(m-2)^2,如果最后所有的球都消除完了还会额外获得1000分。让你输出每一次消除的球的颜色和数量以及得分和位置,最后输出总得分和剩余的球的数量。输出格式看题目。

思路:思路很简单就是每次dfs求出当前图中最大连通块然后消去,然后再移动剩下的球,最后结束条件是最大连通块的大小不超过1(至少有两个相同的球才能消除)。就是写起来比较麻烦,细节方面多注意点。还有就是图的左下角坐标是(1,1),然后每次输出消除的连通块的位置要求是当前连通块中最靠左下角的那个球的位置(开始没看到这个条件wa了好多次。。),所以我们可以从左下角开始往上遍历,这样找到的某个连通块的第一个球的位置就满足条件了。

代码如下

#include <iostream> #include <cmath>#include <algorithm>#include <cstring>#include <queue>#include <cstdio>using namespace std; #define ll long long int int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};char mp[20][20];int vis[20][20];int shu;void dfs(int x,int y,char col){    for(int i=0;i<4;i++)    {        int xx=x+dx[i];        int yy=y+dy[i];        if(xx>=0&&xx<10&&yy>=0&&yy<15&&vis[xx][yy]==0&&mp[xx][yy]==col)        {            vis[xx][yy]=1;            shu++;            dfs(xx,yy,col);        }    }}void del(int x,int y,char col)//消除当前最大的连通块{    for(int i=0;i<4;i++)    {        int xx=x+dx[i];        int yy=y+dy[i];        if(xx>=0&&xx<10&&yy>=0&&yy<15&&mp[xx][yy]==col)        {            mp[xx][yy]='#';            del(xx,yy,col);        }    }}void change()//移动剩下的球的位置{    for(int j=0;j<15;j++)//先考虑移动每一列上球往下掉    {        for(int i=9;i>=0;i--)        {            if(mp[i][j]=='#')            {                int k=i-1;                while(k>=0)                {                    if(mp[k][j]!='#')                    {                        mp[i][j]=mp[k][j];                        mp[k][j]='#';                        break;                    }                    k--;                }            }        }    }    for(int j=0;j<15;j++)//然后再考虑移动整列    {        if(mp[9][j]=='#')        {            int flag=0;            int k=j+1;            while(k<15)            {                if(mp[9][k]!='#')                {                    flag=1;                    break;                }                k++;            }            if(flag==0)            return ;            int l=k-j;            for(int w=k;w<15;w++)            {                for(int z=0;z<10;z++)                mp[z][w-l]=mp[z][w];            }            int w=14;            for(int w=14;w>=15-l;w--)            {                for(int z=0;z<10;z++)                mp[z][w]='#';            }        }    }}int main() {      int T;    scanf("%d",&T);    for(int t=1;t<=T;t++)    {        for(int i=0;i<10;i++)//存图的时候是从(0,0)开始存的,遍历输出答案的时候注意需要转化下坐标        scanf("%s",&mp[i]);        printf("Game %d:\n\n",t);        int k=1;//当前步数        int num=0;//消除的球的数量        int sum=0;//所得分数        while(1)//开始找最大连通块消除        {            memset(vis,0,sizeof(vis));            int maxn=0;            int x,y;            for(int j=0;j<15;j++)            for(int i=9;i>=0;i--)            {                if(mp[i][j]!='#'&&vis[i][j]==0)                {                    vis[i][j]=1;                    shu=1;                    dfs(i,j,mp[i][j]);                    if(shu>maxn)                    {                        maxn=shu;                        x=i;                        y=j;                    }                }            }            if(maxn==1||maxn==0)//如果最大连通块为0或者1说明已经没法消除了,结束            break;            num+=maxn;            sum+=(maxn-2)*(maxn-2);            char c=mp[x][y];            mp[x][y]='#';            del(x,y,c);//消除当前最大连通块            printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n",k,10-x,y+1,maxn,c,(maxn-2)*(maxn-2));            change();//移动                       k++;        }        if(num==150)//如果全部消除了会获得额外奖励        sum+=1000;        printf("Final score: %ld, with %d balls remaining.\n\n",sum,150-num);           }    return 0;}
原创粉丝点击