P1312 [NOIP2011 提高组] Mayan 游戏
一起来打块。。。。
dnm,调了一晚上==
知识点:模拟,搜索
操作:掉块,消块,移块,判最终是否合法。
掉块:注意有空块的时候才掉,对于每一列从下往上扫一遍就好。
消块:有连续三块才能消,但不是一遇到三块能消,这样如果有连续的五块,剩两块就没法消了,所以对能消的块先打个标记,最后一起消了就好了。注意:如果能消,肯定要执行一次掉块操作,执行完掉块还要进行消块,因为掉块可能会导致重新组合成可以新的可以消的块,直到不能消了位置,用一个循环实现就好。
移块:\(dfs\) 枚举每一步移动哪一个块,记录移动之前的状态方便回溯,过程中把答案记下就好了。
移块时剪枝:一个块向左移,要保证左边没有快,如果向右移要保证右边有不同颜色的块。
判最终是否合法:看最下面一行是否为空就好了。
code
/*
work by:Ariel_
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define ll long long
#define rg register
using namespace std;
int read(){
int x = 0,f = 1; char c = getchar();
while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
return x*f;
}
struct Ans{
int x, y, d;
}ans[6];
int n, k, mp[6][8], fag, last[6][6][8], Step;//mp[i][j]: x = i, y = j; 起始从(1, 1)开始,按照数学坐标系模拟
bool res[6][8];
void down() {//掉落
for (int i = 1; i <= 5; i++) {
int x = 0;
for (int j = 1; j <= 7; j++) {
if (!mp[i][j]) x++;
else {
if (x == 0) continue;
mp[i][j - x] = mp[i][j], mp[i][j] = 0;
}
}
}
}
bool delet() {//消除操作
int flag = 0;
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
if (i - 1 >= 1 && i + 1 <= 5 && mp[i - 1][j] == mp[i][j] && mp[i + 1][j] == mp[i][j] && mp[i][j]) {
res[i - 1][j] = 1, res[i][j] = 1, res[i + 1][j] = 1, flag = 1;
}
if(j - 1 >= 1 && j + 1 <= 7 && mp[i][j - 1] == mp[i][j] && mp[i][j] == mp[i][j + 1] && mp[i][j]) {
res[i][j] = 1, res[i][j - 1] = 1, res[i][j + 1] = 1, flag = 1;
}
}
}
if (flag == 0) return false;
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
if (res[i][j]) mp[i][j] = 0, res[i][j] = 0;
}
}
return true;
}
void move(int x, int y, int d) {
swap(mp[x][y], mp[x + d][y]);
down();
while(delet()) down();//连续消
}
bool check() {
for (int i = 1; i <= 5; i++) if (mp[i][1]) return 0;
return 1;
}
void copy(int x) {
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
last[x][i][j] = mp[i][j];
}
}
}
void dfs(int step) {
if (check()) {
for (int i = 1; i <= n; i++) {
printf("%d %d %d\n", ans[i].x, ans[i].y, ans[i].d);
}
exit(0);
}
if (step == n + 1) return ;//超步数
copy(step);
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
if (mp[i][j]) {
if (i + 1 <= 5 && mp[i][j] != mp[i + 1][j]){//右侧没有方块
move(i, j, 1);
ans[step].x = i - 1, ans[step].y = j - 1, ans[step].d = 1;
dfs(step + 1);
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
mp[i][j] = last[step][i][j];
}
}
ans[step].x = -1, ans[step].y = -1, ans[step].d = -1;
}
if (i - 1 >= 1 && mp[i - 1][j] == 0) {
move(i, j, -1);
ans[step].x = i - 1, ans[step].y = j - 1, ans[step].d = -1;
dfs(step + 1);
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 7; j++) {
mp[i][j] = last[step][i][j];
}
}
ans[step].x = -1, ans[step].y = -1, ans[step].d = -1;
}
}
}
}
}
int main(){
n = read();
memset(ans, -1, sizeof ans);
for (int i = 1, tot, x; i <= 5; i++) {
x = read(), tot = 1;
while(x) {mp[i][tot++] = x, x = read();}
}
dfs(1);
puts("-1");
return 0;
}