poj1027 模拟
2016-03-11 22:22
477 查看
题意:在一个固定大小为10x15的矩形区域A内被RGB三种颜色的小球填满,每次可以选择同种颜色(上下左右)连通小球数>=2的区域进行删除,删除后,上方的小球会下落,如果有空列,将其右边的列进行整列左移,移动后小球的相对顺序不变。设m(m>=2)为删除个数,每次的得分为(m-2)*(m-2),如果最后所有的小球全部能够删除,奖励1000分。当区域A没有剩余小球或是最大连通区域的小球个数为1时游戏结束。现每步删除最大的连通区域,如果存在多个相同的最大连通区域,选择最左最下的小球所在的连通区域,输出每步得分和总得分。
算法:模拟,寻找最大连通区域时可用dfs或bfs
算法:模拟,寻找最大连通区域时可用dfs或bfs
#include <iostream> #include <string.h> using namespace std; char map[11][26]; int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; bool vis[11][16]; int cnt; int curr_row,curr_col; bool inMap(int row, int col) { return (row>=0 && row<10 && col>=0 && col<15); } // 计算最大连通区域 void dfs(int row, int col) { vis[row][col] = true; cnt++; for (int i=0; i<4; i++) { int nr = row + dir[i][0]; int nc = col + dir[i][1]; if (inMap(nr,nc) && !vis[nr][nc] && map[nr][nc]==map[row][col]) { dfs(nr,nc); } } } void remove(int row, int col) { char c = map[row][col]; map[row][col] = ' '; for (int i=0; i<4; i++) { int nr = row + dir[i][0]; int nc = col + dir[i][1]; if (inMap(nr,nc) && map[nr][nc]==c) { remove(nr,nc); } } } int chooseBall() { memset(vis,false,sizeof(vis)); int num = -1; int row,col; // 从左下角开始选 for (int i=0; i<15; i++) { for (int j=0; j<10; j++) { if (map[j][i] == ' ' || vis[j][i]) { continue; } cnt = 0; dfs(j,i); if (cnt > num) { num = cnt; curr_row = j; curr_col = i; } } } return num; } // 小球落下+非空行左移 void fresh() { int i,j,k; bool isEmpty[20]; // isEmpty[i]=true:第i列为空 memset(isEmpty,false,sizeof(isEmpty)); for (i=0; i<15; i++) { // 找每一列的第一个非空元素 int ballNum = -1; for (j=0; j<10; j++) { if (map[j][i] != ' ') { map[++ballNum][i] = map[j][i]; } } // 如果是空行 if (ballNum == -1) { isEmpty[i] = true; continue; } // 小球落下 for (k=ballNum+1; k<10; k++) { map[k][i] = ' '; } } // 非空行左移 for (i=0; i<15; i++) { if (isEmpty[i]) { for (j=i+1; j<15; j++) { if (!isEmpty[j]) { break; } } if (j >= 15) { break; } isEmpty[j] = true; isEmpty[i] = false; for (k=0; k<10; k++) { map[k][i] = map[k][j]; map[k][j] = ' '; } } } } int main() { int cases; cin >> cases; for (int i=1; i<=cases; i++) { for (int j=9; j>=0; j--) { cin >> map[j]; } cout << "Game " << i << ":" << endl << endl; int steps = 1; int score = 0; int ballNum; int leftBallNum=150; while (true) { ballNum = chooseBall(); if (ballNum == -1) { score += 1000; break; } else if (ballNum == 1) { break; } leftBallNum -= ballNum; cout << "Move " << steps++ << " at (" << curr_row+1 << "," << curr_col+1 << "): removed " << ballNum << " balls of color " << map[curr_row][curr_col] << ", got " << (ballNum-2)*(ballNum-2) << " points." << endl; score += (ballNum-2) * (ballNum-2); remove(curr_row,curr_col); fresh(); } cout << "Final score: " << score << ", with " << leftBallNum << " balls remaining. " << endl << endl; } }
#include <iostream> #include <queue> #include <string.h> using namespace std; char map[11][26]; int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; bool vis[11][16]; int cnt; int curr_row,curr_col; bool inMap(int row, int col) { return (row>=0 && row<10 && col>=0 && col<15); } // 计算最大连通区域 void bfs(int row, int col) { int q[160]; int tail,head; tail = head = 0; int loc = row * 15 + col; vis[row][col] = true; q[tail++] = loc; while(head < tail) { loc = q[head++]; cnt++; for (int i=0; i<4; i++) { int nr = loc/15 + dir[i][0]; int nc = loc%15 + dir[i][1]; if (inMap(nr,nc) && !vis[nr][nc] && map[nr][nc]==map[row][col]) { vis[nr][nc] = true; q[tail++] = nr*15+nc; } } } } // 将从(row,col)开始的连通区域置为空 void remove(int row, int col) { char c = map[row][col]; map[row][col] = ' '; for (int i=0; i<4; i++) { int nr = row + dir[i][0]; int nc = col + dir[i][1]; if (inMap(nr,nc) && map[nr][nc]==c) { remove(nr,nc); } } } int chooseBall() { memset(vis,false,sizeof(vis)); int num = -1; int row,col; // 最左,最下 for (int i=0; i<15; i++) { for (int j=0; j<10; j++) { if (map[j][i] == ' ' || vis[j][i]) { continue; } cnt = 0; bfs(j,i); if (cnt > num) { num = cnt; curr_row = j; curr_col = i; } } } return num; } // 小球落下+非空行左移 void fresh() { int i,j,k; bool isEmpty[20]; // isEmpty[i]=true:第i列为空 memset(isEmpty,false,sizeof(isEmpty)); for (i=0; i<15; i++) { // 找每一列的第一个非空元素 int ballNum = -1; for (j=0; j<10; j++) { if (map[j][i] != ' ') { map[++ballNum][i] = map[j][i]; } } // 如果是空行 if (ballNum == -1) { isEmpty[i] = true; continue; } // 小球落下 for (k=ballNum+1; k<10; k++) { map[k][i] = ' '; } } // 非空行左移 for (i=0; i<15; i++) { if (isEmpty[i]) { for (j=i+1; j<15; j++) { if (!isEmpty[j]) { break; } } if (j >= 15) { break; } isEmpty[j] = true; isEmpty[i] = false; for (k=0; k<10; k++) { map[k][i] = map[k][j]; map[k][j] = ' '; } } } } int main() { int cases; cin >> cases; for (int i=1; i<=cases; i++) { for (int j=9; j>=0; j--) { cin >> map[j]; } cout << "Game " << i << ":" << endl << endl; int steps = 1; int score = 0; int ballNum; int leftBallNum=150; while (true) { ballNum = chooseBall(); if (ballNum == -1) { score += 1000; break; } else if (ballNum == 1) { break; } leftBallNum -= ballNum; cout << "Move " << steps++ << " at (" << curr_row+1 << "," << curr_col+1 << "): removed " << ballNum << " balls of color " << map[curr_row][curr_col] << ", got " << (ballNum-2)*(ballNum-2) << " points." << endl; score += (ballNum-2) * (ballNum-2); remove(curr_row,curr_col); fresh(); } cout << "Final score: " << score << ", with " << leftBallNum << " balls remaining. " << endl << endl; } }
相关文章推荐
- Transformation 能将 Windows XP/Server 2003 操作系统,完美地模拟成 Windows Vista 的软件
- 用javascript和css模拟select的脚本
- PHP模拟asp.net的StringBuilder类实现方法
- C#使用ImitateLogin模拟登录百度
- javascript用层模拟可移动的小窗口
- 自编jQuery插件实现模拟alert和confirm
- JS模拟按钮点击功能的方法
- PHP模拟asp中response类实现方法
- 模拟Spring的简单实现
- javascript 模拟点击广告
- JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
- php实现模拟post请求用法实例
- JavaScript实现MIPS乘法模拟的方法
- 模拟xcopy的函数
- JS模拟实现Select效果代码
- php模拟服务器实现autoindex效果的方法
- C# SendInput 模拟鼠标操作的实现方法
- PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
- js实现模拟银行卡账号输入显示效果
- JS模拟并美化的表单控件完整实例