博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏
阅读量:4517 次
发布时间:2019-06-08

本文共 10851 字,大约阅读时间需要 36 分钟。

Mayan游戏

题目描述

Mayan puzzle是最近流行起来的一个游戏。游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上。游戏通关是指在规定的步数内消除所有的方块,消除方块的规则如下:

1 、每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将 交换位置(参见输入输出样例说明中的图6 到图7 );如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从目标位置上掉落(直到不悬空,参见下面图1 和图2);

2 、任一时刻,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除(参见图1 到图3)。

注意:

a) 如果同时有多组方块满足消除条件,几组方块会同时被消除(例如下面图4 ,三个颜色为1 的方块和三个颜色为 2 的方块会同时被消除,最后剩下一个颜色为 2 的方块)。

b) 当出现行和列都满足消除条件且行列共享某个方块时,行和列上满足消除条件的所有方块会被同时消除(例如下面图5 所示的情形,5 个方块会同时被消除)。

3 、方块消除之后,消除位置之上的方块将掉落,掉落后可能会引起新的方块消除。注意:掉落的过程中将不会有方块的消除。

上面图1 到图 3 给出了在棋盘上移动一块方块之后棋盘的变化。棋盘的左下角方块的坐标为(0, 0 ),将位于(3, 3 )的方块向左移动之后,游戏界面从图 1 变成图 2 所示的状态,此时在一竖列上有连续三块颜色为4 的方块,满足消除条件,消除连续3 块颜色为4 的方块后,上方的颜色为3 的方块掉落,形成图 3 所示的局面。

输入输出格式

输入格式:

输入文件mayan.in,共 6 行。

第一行为一个正整数n ,表示要求游戏通关的步数。

接下来的5 行,描述 7*5 的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0 结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1 开始顺序编号,相同数字表示相同颜色)。

输入数据保证初始棋盘中没有可以消除的方块。

输出格式:

输出文件名为mayan.out。

如果有解决方案,输出 n 行,每行包含 3 个整数x,y,g ,表示一次移动,每两个整数之间用一个空格隔开,其中(x ,y)表示要移动的方块的坐标,g 表示移动的方向,1 表示向右移动,-1表示向左移动。注意:多组解时,按照 x 为第一关健字,y 为第二关健字,1优先于-1 ,给出一组字典序最小的解。游戏界面左下角的坐标为(0 ,0 )。

如果没有解决方案,输出一行,包含一个整数-1。

输入输出样例

输入样例#1:
31 02 1 02 3 4 03 1 02 4 3 4 0
输出样例#1:
2 1 13 1 13 0 1

说明

【输入输出样例说明】

按箭头方向的顺序分别为图6 到图11

样例输入的游戏局面如上面第一个图片所示,依次移动的三步是:(2 ,1 )处的方格向右移动,(3,1 )处的方格向右移动,(3 ,0)处的方格向右移动,最后可以将棋盘上所有方块消除。

【数据范围】

对于30% 的数据,初始棋盘上的方块都在棋盘的最下面一行;

对于100%的数据,0 < n≤5 。

noip2011提高组day1第3题

 

【题解】

阻止我AK掉人品的一道题。。不过在考场上可能多1h就能A了吧。。

留了两个半小时敲这个题,时间长感觉有点松懈了。。

还有两个月NOIP,两个月后可能场上可A?

 

这里有三个剪枝

1、右边左拉等价左边右拉,所以只有左边为0时才左拉,否则右拉

2、若右拉的格子颜色等于他的右边, 交换就没有意义了

3、某种颜色>=1<=2,方案不可行

注意消除的时候,横着消的地方要同时处理竖着消,竖着消的地方要

同时处理横着消,可能有2~4个点卡这个地方?

1 #include 
2 #include
3 #include
4 #include
5 #define max(a, b) ((a) > (b) ? (a) : (b)) 6 7 inline void read(int &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 int ma, g[9][6], flag; 16 17 char dir[10]; 18 int ansx[10], ansy[10]; 19 20 struct Node 21 { 22 int g[9][6], re, num[11]; 23 Node() 24 { 25 re = 0; 26 memset(g, 0, sizeof(g)); 27 } 28 }; 29 inline void put(Node a) 30 { 31 for(register int i = 1;i <= 7;++ i) 32 { 33 for(register int j = 1;j <= 5;++ j) 34 printf("%d ", a.g[i][j]); 35 putchar('\n'); 36 } 37 putchar('\n'); 38 putchar('\n'); 39 } 40 inline void swap(int &a, int &b) 41 { 42 int tmp = a;a = b;b = tmp; 43 } 44 45 int del(int x, int y, Node& tmp) 46 { 47 //左右删除 48 int l = y, r = y; 49 int color = tmp.g[x][y]; 50 while(color == tmp.g[x][l]) -- l; 51 ++ l; 52 while(color == tmp.g[x][r]) ++ r; 53 -- r; 54 if(r - l + 1 >= 3) 55 { 56 for(register int i = l;i <= r;++ i) 57 tmp.g[x][i] = 0; 58 tmp.re -= (r - l + 1); 59 tmp.num[color] -= (r - l + 1); 60 for(register int i = l;i <= r;++ i) 61 { 62 tmp.g[x][i] = color; 63 ++ tmp.re; 64 ++ tmp.num[color]; 65 int up = x, down = x; 66 while(color == tmp.g[up][i])-- up; 67 ++ up; 68 while(color == tmp.g[down][i])++ down; 69 -- down; 70 if(down - up + 1 >= 3) 71 { 72 for(register int j = up;j <= down;++ j) 73 tmp.g[j][i] = 0; 74 tmp.re -= (down - up + 1); 75 tmp.num[color] -= (down - up + 1); 76 } 77 else -- tmp.re, tmp.g[x][i] = 0, --tmp.num[color]; 78 } 79 return 1; 80 } 81 82 //上下 83 int up = x, down = x; 84 while(color == tmp.g[up][y])-- up; 85 ++ up; 86 while(color == tmp.g[down][y])++ down; 87 -- down; 88 if(down - up + 1 >= 3) 89 { 90 for(register int i = up;i <= down;++ i) 91 tmp.g[i][y] = 0, --tmp.num[color]; 92 tmp.re -= (down - up + 1); 93 for(register int i = up;i <= down;++ i) 94 { 95 ++ tmp.re, tmp.g[i][y] = color, ++tmp.num[color]; 96 int l = y, r = y; 97 while(tmp.g[i][l] == color)-- l; 98 ++ l; 99 while(tmp.g[i][r] == color)++ r;100 -- r;101 if(r - l + 1 >= 3)102 {103 for(register int a = l;a <= r;++ a)104 tmp.g[i][a] = 0;105 tmp.re -= (r - l + 1);106 tmp.num[color] -= (r - l + 1);107 }108 else -- tmp.re, tmp.g[i][y] = 0, --tmp.num[color];109 }110 111 return 1;112 }113 return 0;114 }115 116 int diao(Node& tmp)117 {118 int re = 0;119 for(register int j = 1;j <= 5;++ j)120 {121 int now = 8;122 for(register int i = 7;i >= 1;-- i)123 {124 if(tmp.g[i][j] && now - 1 == i)-- now;125 else if(tmp.g[i][j])126 {127 tmp.g[now - 1][j] = tmp.g[i][j];128 tmp.g[i][j] = 0;129 re = 1;130 -- now;131 }132 }133 }134 return re;135 }136 int k;137 void dfs(int step, Node now)138 {139 for(register int i = 1;i <= 10;++ i)140 if(now.num[i] > 0 && now.num[i] < 3)return;141 //如果步数走完了 142 if(step > ma)143 {144 //没有剩下的了 145 if(now.re == 0)146 {147 //输出方案 148 flag = 1;149 for(register int i = 1;i <= ma;++ i)150 printf("%d %d %d\n", ansy[i] - 1, ansx[i] - 1, dir[i]);151 return; 152 }153 return;154 }155 Node re;156 157 //枚举拉点(i,j) 158 for(register int j = 1;j <= 5;++ j)159 {160 for(register int i = 7;i >= 1;-- i)161 {162 //如果(i,j)有方块 163 if(now.g[i][j])164 {165 re = now;166 if(i == 3 && j == 3 && step == 2) 167 ++ k;168 if(i == 5 && j == 4 && step == 3) 169 ++ k;170 if(i == 1 && j == 4 && step == 4) 171 ++ k;172 if(i == 4 && j == 4 && step == 5) 173 ++ k;174 //右拉 175 if(j < 5)176 {177 //右拉有意义 178 if(re.g[i][j] != re.g[i][j + 1])179 { 180 //拉动 181 swap(re.g[i][j], re.g[i][j + 1]);182 //掉落 183 int tmp1 = i, tmp2 = j;184 while(!re.g[tmp1 + 1][tmp2] && tmp1 + 1 <= 7)185 {186 swap(re.g[tmp1 + 1][tmp2], re.g[tmp1][tmp2]);187 ++ tmp1;188 }189 //连环操作 190 int f = 0;191 //如果上一次删除成功,需要重新扫描、删除 192 while(true)193 {194 f = 0;195 //对于每个点(x,y),尝试进行删除 196 for(register int x = 1;x <= 7;++x)197 { 198 for(register int y = 1;y <= 5;++ y)199 {200 //如果(x,y)没有颜色,就不尝试删除了 201 if(!re.g[x][y])continue;202 //尝试删除 203 del(x, y, re);204 }205 }206 //掉落207 f = diao(re);208 //回去,直到没有更新为止 209 if(!f)break;210 }211 //记录答案 212 ansx[step] = 7 - i + 1;213 ansy[step] = j;214 dir[step] = 1;215 dfs(step + 1, re); 216 if(flag)return;217 }218 } 219 re = now;220 if(i == 6 && j == 2 && step == 1) 221 ++ k;222 //左拉223 if(j > 1 && re.g[i][j - 1] == 0)224 {225 if(re.g[i][j] != re.g[i][j - 1])226 {227 //拉动 228 swap(re.g[i][j], re.g[i][j - 1]);229 //掉落 230 int tmp1 = i, tmp2 = j;231 while(!re.g[tmp1 + 1][tmp2] && tmp1 + 1 <= 7)232 {233 swap(re.g[tmp1 + 1][tmp2], re.g[tmp1][tmp2]);234 ++ tmp1;235 }236 //连环操作 237 int f = 0;238 //如果上一次删除成功,需要重新扫描、删除 239 while(true)240 {241 f = 0;242 //对于每个点(x,y),尝试进行删除 243 for(register int x = 1;x <= 7;++x)244 { 245 for(register int y = 1;y <= 5;++ y)246 {247 //如果(x,y)没有颜色,就不尝试删除了 248 if(!re.g[x][y])continue;249 //尝试删除 250 f = del(x, y, re);251 }252 }253 //掉落254 f = diao(re);255 //回去,直到没有更新为止 256 if(!f)break;257 }258 //记录答案 259 ansx[step] = 7 - i + 1;260 ansy[step] = j;261 dir[step] = -1;262 dfs(step + 1, re);263 if(flag)return;264 }265 }266 }267 }268 }269 }270 271 int main()272 {273 read(ma);274 register int tmp, num = 0;275 Node tt;276 for(register int i = 1;i <= 5;++ i)277 {278 int j = 7;279 read(tmp);280 while(tmp)tt.g[j][i] = tmp, -- j, ++num, ++ tt.num[tmp], read(tmp);281 }282 tt.re = num;283 dfs(1, tt);284 if(!flag)printf("-1");285 return 0;286 }
NOIP2011 Day1T3

 

 

转载于:https://www.cnblogs.com/huibixiaoxing/p/7508240.html

你可能感兴趣的文章
Atan2
查看>>
ThinkSNS+ 是如何计算字符显示长度的
查看>>
JSTL的使用
查看>>
c#推箱子
查看>>
随机数据生成
查看>>
linux中文输入法 ibus
查看>>
在infoWindow中显示Geocode server(地理编码服务)
查看>>
DB2时间函数大全
查看>>
Latex中关于参考文献的一些经验
查看>>
文件存储,块存储,对象存储的区别
查看>>
python使用
查看>>
poj 3190 Stall Reservations (贪心+优先队列)
查看>>
prepareStatement的用法和解释
查看>>
JS-Math内置对象
查看>>
[Java面试五]Spring总结以及在面试中的一些问题.
查看>>
Maven项目环境搭建实例.
查看>>
ES6学习笔记
查看>>
apply和call的区别
查看>>
linux虚拟机调整分辨率
查看>>
IOS开发学习笔记007-数据结构
查看>>