【正经题解】Mayan 游戏
2024-02-21 10:59:01
发布于:美国
19阅读
0回复
0点赞
向右的时候如果右方颜色相同则跳过
向左的时候如果左方并非是空,则跳过(否则可以选择其左侧方块右移,这样字典序更小)
需要更短时间的话可以根据每一步当前图的状态是否出现某种颜色小于 个来进行剪枝。因为你刷新图的时候其实就可以顺手统计,所以其实并不怎么费时,但是剪枝效果满满
至于实现细节的话,掉落可以看 的代码,刷新的时候先掉落一下,再给要消除的东西打标记。最后根据标记删除方块,步骤爆搜即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define REP(i,l,r) for(int i=l;i<r;++i)
const int dx[4]={-1,0,1,0}, dy[4]={0,1,0,-1};
int ansx[6], ansy[6], ansmv[6];
int mp[7][5][7], N;
bool vis[5][7];
inline void hei(int d, int x, int y, int mv){
ansx[d]=x, ansy[d]=y, ansmv[d]=mv;
}
inline bool inbound(int x, int y){ return 0<=x&&x<5&&0<=y&&y<7;}
void fall(int d){
REP(i,0,5){ int sz=0;
REP(j,0,7) if (mp[d][i][j])
mp[d][i][sz++]=mp[d][i][j];
while (sz < 7) mp[d][i][sz++] = 0;
}
}
inline void refresh(int d){
int tim = 0;
for (bool cg = true; cg;){
cg = false, fall(d);
REP(i,0,5) REP(j,0,7) if (mp[d][i][j]){
if (i < 3){
if (mp[d][i][j]==mp[d][i+1][j]&&mp[d][i][j]==mp[d][i+2][j]){
cg = vis[i][j] = vis[i+1][j] = vis[i+2][j] = true;
}
}
if (j < 5){
if (mp[d][i][j]==mp[d][i][j+1]&&mp[d][i][j]==mp[d][i][j+2]){
cg = vis[i][j] = vis[i][j+1] = vis[i][j+2] = true;
}
}
}
REP(i,0,5) REP(j,0,7) if (vis[i][j]) mp[d][i][j] = vis[i][j] = 0;
}
}
bool solve(int dep){
REP(i,0,5) REP(j,0,7) mp[dep][i][j] = mp[dep-1][i][j];
refresh(dep);
if (dep == N+1){
REP(i,0,5) if (mp[dep][i][0]) return false;
return true;
}
REP(i,0,5) REP(j,0,7) if (mp[dep][i][j]){
if (i < 4 && mp[dep][i][j]!=mp[dep][i+1][j]){ // 1
hei(dep, i, j, 1);
swap(mp[dep][i][j], mp[dep][i+1][j]);
if (solve(dep+1)) return true;
swap(mp[dep][i][j], mp[dep][i+1][j]);
}
if (i && !mp[dep][i-1][j]){ // -1
hei(dep, i, j, -1);
swap(mp[dep][i][j], mp[dep][i-1][j]);
if (solve(dep+1)) return true;
swap(mp[dep][i][j], mp[dep][i-1][j]);
}
}
return false;
}
int main(){
scanf("%d", &N);
REP(i,0,5) REP(j,0,9){
int x; scanf("%d", &x);
if (!x) break;
mp[0][i][j] = x;
}
bool fg = solve(1);
if (fg){ REP(i,1,N+1) printf("%d %d %d\n", ansx[i],ansy[i],ansmv[i]);}
else puts("-1");
return 0;
}
这里空空如也
有帮助,赞一个