1. 程式人生 > >洛谷 P1312 [ NOIP 2011 ] Mayan遊戲 —— 搜索+模擬

洛谷 P1312 [ NOIP 2011 ] Mayan遊戲 —— 搜索+模擬

i++ show 函數 .org 兩個 左移 nsx string pre

題目:https://www.luogu.org/problemnew/show/P1312

還是不擅長這種題,所以參考了一下TJ;

其實也很好搜,按字典序,先搜右移,再搜左移;

不交換相同顏色的兩個格子,因為浪費;

左移就不交換了,避免重復,只有左邊為空時左移;

寫個處理下落的 fall 函數,再寫個處理消格子的 refresh 函數(其中用到了 fall ),就可以方便地搜索了!

我存的是行和列,所以和坐標正好相反,一定要註意字典序的處理!

優美。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; int n,mp[10][10][10],ansx[10],ansy[10],ansm[10]; bool vis[10][10]; void fall(int s) { for(int j=1,sz;j<=5;j++) { sz=0; for(int i=1;i<=7;i++) if(mp[s][i][j])mp[s][++sz][j]=mp[s][i][j]; while(sz<7)mp[s][++sz][j]=0;// } }
void refresh(int s) { bool fl=0; while(1) { fl=0; fall(s); for(int i=1;i<=7;i++) for(int j=1;j<=5;j++) { if(!mp[s][i][j])continue;// if(i<=5&&mp[s][i][j]==mp[s][i+1][j]&&mp[s][i][j]==mp[s][i+2][j]) { fl
=1; vis[i][j]=vis[i+1][j]=vis[i+2][j]=1; } if(j<=3&&mp[s][i][j]==mp[s][i][j+1]&&mp[s][i][j]==mp[s][i][j+2]) { fl=1; vis[i][j]=vis[i][j+1]=vis[i][j+2]=1; } } if(!fl)break; for(int i=1;i<=7;i++) for(int j=1;j<=5;j++) if(vis[i][j])mp[s][i][j]=0,vis[i][j]=0; } } bool dfs(int s) { for(int i=1;i<=7;i++) for(int j=1;j<=5;j++)mp[s][i][j]=mp[s-1][i][j]; refresh(s); if(s>n) { for(int j=1;j<=5;j++) if(mp[s][1][j])return 0; return 1; } for(int j=1;j<=5;j++)//字典序! for(int i=1;i<=7;i++) if(mp[s][i][j]) { if(j<5&&mp[s][i][j]!=mp[s][i][j+1])//1 { ansx[s]=i; ansy[s]=j; ansm[s]=1; swap(mp[s][i][j],mp[s][i][j+1]); if(dfs(s+1))return 1; swap(mp[s][i][j],mp[s][i][j+1]); } if(j>1&&!mp[s][i][j-1])//-1 { ansx[s]=i; ansy[s]=j; ansm[s]=-1; swap(mp[s][i][j],mp[s][i][j-1]); if(dfs(s+1))return 1; swap(mp[s][i][j],mp[s][i][j-1]); } } return 0; } int main() { scanf("%d",&n); for(int j=1;j<=5;j++) for(int i=1,x;i<=8;i++) { scanf("%d",&x); if(!x)break; mp[0][i][j]=x; } if(dfs(1))//1 { for(int i=1;i<=n;i++) printf("%d %d %d\n",ansy[i]-1,ansx[i]-1,ansm[i]);//坐標! } else printf("-1\n"); return 0; }

洛谷 P1312 [ NOIP 2011 ] Mayan遊戲 —— 搜索+模擬