NC16595. [NOIP2011]Mayan 游戏
描述
输入描述
第一行为一个正整数n,表示要求游戏通关的步数。
接下来的5行,描述7*5的游戏界面。每行若干个整数,每两个整数之间用一个空格隔开,每行以一个0结束,自下向上表示每竖列方块的颜色编号(颜色不多于10种,从1开始顺序编号,相同数字表示相同颜色)。
输入数据保证初始棋盘中没有可以消除的方块。
输出描述
如果有解决方案,输出n行,每行包含3个整数x,y,g,表示一次移动,每两个整数之间用一个空格隔开,其中(x,y)表示要移动的方块的坐标,g表示移动的方向,1表示向右移动,-1表示向左移动。注意:多组解时,按照x为第一关健字,y为第二关健字,1优先于-1,给出一组字典序最小的解。游戏界面左下角的坐标为(0,0)。
如果没有解决方案,输出一行,包含一个整数-1。
示例1
输入:
3 1 0 2 1 0 2 3 4 0 3 1 0 2 4 3 4 0
输出:
2 1 1 3 1 1 3 0 1
说明:
C++14(g++5.4) 解法, 执行用时: 369ms, 内存消耗: 500K, 提交时间: 2019-11-02 21:17:32
#include<bits/stdc++.h> 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],mp[7][5][7],N,x;bool vis[5][7]; void hei(int d,int x,int y,int mv){ansx[d]=x;ansy[d]=y;ansmv[d]=mv;} 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; } } 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&&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&&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]){ 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]){ 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){ 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; }
C++ 解法, 执行用时: 340ms, 内存消耗: 404K, 提交时间: 2022-03-30 22:55:47
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> pii; pair<pii,int> ans[5]; int n; struct node { int a[5][7]{0},h[5]{0}; bool sum(){ if(h[0]+h[1]+h[2]+h[3]+h[4]) return true; return false; } bool check() { bool f[5][7],ok=0; memset(f,false,sizeof(f)); for(int i=0;i<5;i++) for(int j=0;j<7;j++) { if(i+2<5&&a[i][j]&&a[i][j]==a[i+1][j]&&a[i][j]==a[i+2][j]) ok=f[i][j]=f[i+1][j]=f[i+2][j]=true; if(j+2<7&&a[i][j]&&a[i][j]==a[i][j+1]&&a[i][j]==a[i][j+2]) ok=f[i][j]=f[i][j+1]=f[i][j+2]=true; } for(int i=0;i<5;i++) for(int j=0;j<7;j++) if(f[i][j]) a[i][j]=0; return ok; } void drop(){ for(int i=0;i<5;i++){ h[i]=0; for(int j=0;j<7;j++) if(a[i][j]) a[i][h[i]++]=a[i][j]; for(int j=h[i];j<7;j++) a[i][j]=0; } } }; void dfs(node b,int k){ if(!b.sum()){ if(k<n) return; for(int i=0;i<n;i++) cout<<ans[i].first.first<<' '<<ans[i].first.second<<' '<<ans[i].second<<endl; exit(0); } if(k==n) return; for(int i=0;i<5;i++){ for(int j=0;j<b.h[i];j++){ if(i<4&&b.a[i][j]!=b.a[i+1][j]){ node c=b; swap(c.a[i][j],c.a[i+1][j]); c.drop(); while (c.check()) c.drop(); ans[k]={{i,j},1}; dfs(c,k+1); } if(i&&!b.a[i-1][j]){ node c=b; swap(c.a[i][j],c.a[i-1][j]); c.drop(); while (c.check()) c.drop(); ans[k]={{i,j},-1}; dfs(c,k+1); } } } } int main() { cin>>n; node b; for(int i=0;i<5;i++){ int c; while (cin>>c&&c) b.a[i][b.h[i]++]=c; } dfs(b,0); cout<<-1<<endl; }