news 2026/9/4 15:28:36

UVa 758 The Same Game

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 758 The Same Game

题目描述

Same\texttt{Same}Same” 是一种单人游戏,棋盘为101010151515列,每个格子包含红色(R)、绿色(G)或蓝色(B)的球。两个球属于同一簇当且仅当它们颜色相同,且可以通过上下左右四个方向经过同色球互相到达。每步操作中,玩家选择一个至少包含两个球的簇,将该簇中所有球从棋盘上移除。随后棋盘按两步压缩:

步骤1\texttt{1}1. 每列中剩余的球向下移动以填补空位,各列内球的顺序保持不变。
步骤2\texttt{2}2. 若有整列为空,则将左侧所有剩余列向左平移,列的顺序保持不变。

游戏目标是移除棋盘上所有球,当所有球被移除或所有簇大小均为111时游戏结束。得分规则:初始得分为000,移除一个包含mmm个球的簇时,得分增加(m−2)2(m - 2)^2(m2)2。若最终所有球被移除,额外奖励100010001000分。

本题要求模拟一种贪心策略:每步选择能形成最大簇的球,若有多个最大簇,选择最靠左的;若仍有并列,则选择这些球中最靠下的。输出每步移除的详细信息以及最终得分。

输入格式

第一行为正整数NNN,表示游戏局数。随后每局游戏由101010行组成,每行包含151515个字符,字符为'R''G''B',表示棋盘从上到下的每一行,从左到右排列。每局游戏之前有一个空行。

输出格式

对于每局游戏,首先输出Game k:并换行。然后按顺序输出每一步的信息,格式为:

Move x at (r,c): removed b balls of color C, got s points.

其中xxx为步数编号(从111开始),rrrccc分别为所选球的行号和列号(行号从底部111到顶部101010,列号从左111到右151515),bbb为移除的球数,CCC为颜色字符,sss为该步得分(不含最终100010001000分奖励)。若游戏结束(所有球被移除或仅剩单球簇),输出:

Final score: s, with b balls remaining.

每局游戏输出后跟一个空行。注意复数形式ballspoints即使在数值为111时也使用。

样例输入

3 RGBGBGRBRRGBGB RGBGRBGRBGRGBRG BRRRGBBRGRGBBB GGRGBGBGRRGGGB GGBGRRRRRBGBRRR BBBBBBBBBBBBB BBBBBBBBBBBBB RRRRRRRRRRRRRR RRRRRRGGGRRRRR GGGGGGGGGGGGGG RRRRRRRRRRRRRR RRRRRRRRRRRRRR GGGGGGGGGGGGGGG GGGGGGGGGGGGGGG BBBBBBBBBBBBB BBBBBBBBBBBBB RRRRRRRRRRRRRRR RRRRRRRRRRRRRR GGGGGGGGGGGGGGG GGGGGGGGGGGGGGG RBGRBGRBGRBGRBG BGRBGRBGRBGRBGR GRBGRBGRBGRBGRB RBGRBGRBGRBGRBGR GRBGRBGRBGRBGRB RGRBGRBGRBGRBGRB BGRBGRBGRBGRBGR GRBGRBGRBGRBGRB RBGRBGRBGRBGRB

样例输出

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.

题目分析

该问题要求严格按照贪心策略模拟游戏过程。每步需找到当前棋盘上最大的同色连通簇(四连通),若多个簇大小相同,选择列号最小的(即最左),若列号仍相同,选择行号最小的(即最底部)。移除该簇后,进行压缩(列内下移,空列左移),然后继续下一轮。当最大簇大小为111或棋盘上球数为000时游戏结束。棋盘尺寸固定为10×1510 \times 1510×15,球数最多150150150,每次移除和压缩操作规模小,直接模拟即可。

解题思路

采用递归Flood fill\texttt{Flood fill}Flood fill统计簇大小并标记访问。每轮扫描棋盘,按列从左到右、行从底到顶的顺序遍历,遇到未访问的非空格,使用floodFill\texttt{floodFill}floodFill统计簇大小,记录最大簇及其位置(行、列)。由于扫描顺序就是列优先、行从底到顶,当遇到更大的簇时更新,相等的簇不更新,因此自然满足“最左、最底”的贪心选择。

选定簇后,使用remove\texttt{remove}remove函数将该簇全部标记为'0'(空),然后调用compress\texttt{compress}compress进行压缩。压缩时,先将每列中非空球从底部向上填入临时数组,然后按从左到右的顺序将非空列依次放置,形成压缩后的棋盘。最后累加得分,若移除球数为mmm,则得分为(m−2)2(m-2)^2(m2)2,并减少剩余球数。当剩余球数为000或最大簇大小为111时停止循环,若剩余球数为000则额外加100010001000分。输出每一步信息及最终得分。

算法时间复杂度O(步数×10×15)O(\text{步数} \times 10 \times 15)O(步数×10×15),每步最大150150150步,棋盘仅150150150格,效率极高。

代码实现

// The Same Game// UVa ID: 758// Verdict: Accepted// Submission Date: 2017-10-22// UVa Run Time: 0.060s//// 版权所有(C)2017,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;charmaze[10][15],shadow[10][15];intvisited[10][15],offset[4][2]={{0,1},{0,-1},{1,0},{-1,0}};voidfloodFill(inti,intj,charold,int&cnt){if(i>=0&&i<=9&&j>=0&&j<=14&&!visited[i][j]&&maze[i][j]==old){cnt++;visited[i][j]=1;for(intk=0;k<4;k++)floodFill(i+offset[k][0],j+offset[k][1],old,cnt);}}voidremove(inti,intj,charold,charreplaced){if(i>=0&&i<=9&&j>=0&&j<=14&&maze[i][j]==old){maze[i][j]=replaced;for(intk=0;k<4;k++)remove(i+offset[k][0],j+offset[k][1],old,replaced);}}voidcompress(){memset(shadow,'0',sizeof(shadow));for(inti=0,x=0;i<15;i++){inty=9;for(intj=9;j>=0;j--){if(maze[j][i]!='0'){shadow[y][x]=maze[j][i];y--;}}if(y!=9)x++;}memcpy(maze,shadow,sizeof(shadow));}intmain(intargc,char*argv[]){cin.tie(0),cout.tie(0),ios::sync_with_stdio(false);intcases=0;cin>>cases;for(intc=1;c<=cases;c++){if(c>1)cout<<'\n';cout<<"Game "<<c<<":\n\n";for(inti=0;i<10;i++)for(intj=0;j<15;j++)cin>>maze[i][j];intballs=150,score=0,step=1;while(true){memset(visited,0,sizeof(visited));intremoved=0,row=-1,column=-1;for(inti=0;i<15;i++)for(intj=9;j>=0;j--){if(visited[j][i]||maze[j][i]=='0')continue;intcnt=0;floodFill(j,i,maze[j][i],cnt);if(removed<cnt)removed=cnt,row=j,column=i;}if(removed==1)break;cout<<"Move "<<step++;cout<<" at ("<<(10-row)<<','<<(column+1);cout<<"): removed "<<removed<<" balls of color ";cout<<maze[row][column]<<", got ";cout<<(removed-2)*(removed-2)<<" points.\n";balls-=removed;score+=(removed-2)*(removed-2);if(balls==0)break;remove(row,column,maze[row][column],'0');compress();}if(balls==0)score+=1000;cout<<"Final score: "<<score<<", with "<<balls<<" balls remaining.\n";}return0;}

总结

本题模拟固定规则的消除游戏,核心在于正确实现簇的统计和棋盘压缩。通过Flood fill\texttt{Flood fill}Flood fill寻找最大簇,利用列优先、行从底到顶的扫描顺序自然满足贪心选择条件。压缩分为列内下移和空列左移两步,使用临时数组可简洁实现。输出格式需注意坐标转换(行号从底部计起)和复数形式。该解法直接且高效,适用于固定大小的棋盘,是模拟类题目的典型范例。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 7:23:54

Scrapling 网络爬取框架 3 条命令装好,自适应解析开箱即用

Scrapling 网络爬取框架 3 条命令装好&#xff0c;自适应解析开箱即用 【免费下载链接】Scrapling &#x1f577;️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! 项目地址: https://gitcode.com/GitHub_Trend…

作者头像 李华
网站建设 2026/9/2 11:25:15

自进化AI的隐形陷阱:换个Harness就变笨?工程化解法

很多做 LLM 应用的开发者都遇到过这样一种非常诡异的场景&#xff1a;基座模型一个版本没换&#xff0c;prompt 模板也只是在原有基础上微调&#xff0c;结果一换评估脚本&#xff0c;分数立刻掉了十个点&#xff1b;或者今天在测试环境里还能稳定运行的 Agent&#xff0c;部署…

作者头像 李华
网站建设 2026/9/1 14:34:50

Hermes Agent日志监控实战:从ELK采集到OTLP导出

Hermes Agent日志监控实战&#xff1a;从ELK采集到OTLP导出 【免费下载链接】hermes-agent The agent that grows with you 项目地址: https://gitcode.com/GitHub_Trending/he/hermes-agent 本文交付一套可运行的 Hermes Agent 日志监控 方案&#xff1a;用项目自带的日…

作者头像 李华
网站建设 2026/9/2 11:49:33

Git分支按最后提交时间排序:命令用法与分支清理实战

在实际 Git 仓库里&#xff0c;分支数量一旦多起来&#xff0c;按字母顺序展示的 git branch 列表几乎不提供有效信息。开发者真正想知道的是&#xff1a;哪些分支最近还在提交&#xff0c;哪些分支已经几个月没有动静&#xff0c;哪些分支可以进入清理流程。按最后提交时间&…

作者头像 李华