題目鏈結
由於是暴搜題,所以這篇部落格只講怎麼優化剪枝,以及一些細節。
模擬消除思路:因為消除可以拆分成小的橫條或豎條,而這些條的長度至少為三,所以一塊可消除的區域至少會有乙個中心點。這裡的中心點可以不在正中間,只需要不是條上的第乙個或者最後乙個。
於是列舉中間點,搜尋它為中心最多向四個方向能擴充套件多遠。如果搜尋出來的橫向滿足長度要求,或豎向滿足長度要求,就給他們打上乙個標記。
注意,這裡只是打上標記,不能直接清零,很可能另乙個方塊的結算還得用到這個方塊。
等到列舉所有的中間點並給所有可消除的方塊打上標記之後,可以把所有標記上的方塊清空。然後檢查有沒有地方可以落下去。
注意所有方塊落下去之後還有可能接著消消樂,所以在落完之後還要再迴圈回去檢查有沒有可消除的方塊。這裡使用乙個遞迴的**來實現。
int count(intx)
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
if(vis[i][j])
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
if(!map[x][i][j])
if(flag) cnt+=count(x);
return
cnt;
}
注意最後倒數第三行。flag表示的是有沒有方塊落下,因為有落下方塊就有新一輪消除的可能性,所以可以遞迴這個函式,直到沒有任何方塊落下為止。此時遞迴終止,開始回溯計算答案。
再說說剪枝的幾個小技巧。
1、優先考慮座標字典序小的向右移動,這樣一旦搜到答案就是字典序最小的解。
2、只有當左邊沒有方塊的時候才向左移動,否則右面方塊向左移動等價於左面方塊向右移動,而這個狀態已經搜過了。
3、不交換兩個顏色相同的方塊。這個沒什麼好說的。
最後給出**。
#include#include#include
#include
#include
using
namespace
std;
inline
long
long
read()
while
(isdigit(ch))
return num*f;
}int
num;
int n=7,m=5
;int
max;
int map[10][10][10
];int posx[100],posy[100],move[100
];inline
void copy(int
x)int count(int
x)
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
if(vis[i][j])
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
if(!map[x][i][j])
if(flag) cnt+=count(x);
return
cnt;
}
void dfs(int use,int
deep)
return
; }
copy(deep);
for(register int j=1;j<=m;++j)
for(register int i=1;i<=n;++i)
if(!map[deep][i][j-1]&&j>1
)
int q=count(deep+1
); dfs(use-q,deep+1
); copy(deep);}}
}int
main()
dfs(start,0);
printf("-1
");return0;
}
Luogu P1312 Mayan遊戲 搜尋
p1312 mayan遊戲 mayan puzzle是最近流行起來的乙個遊戲。遊戲介面是乙個 7 行 times 5 列的棋盤,上面堆放著一些方塊,方塊不能懸空堆放,即方塊必須放在最下面一行,或者放在其他方塊之上。遊戲通關是指在規定的步數內消除所有的方塊,消除方塊的規則如下 1 每步移動可以且僅可以...
洛谷P1312 Mayan遊戲
題目描述 見鏈結 解析 直接模擬和搜尋即可,注意儲存好資料,防止回溯時丟失。mayan遊戲 乙個模擬程度大於搜尋的搜尋題 大體模擬過程 移動 下降 消除 repeat 到達規定步數判斷是否消除完 具體剪枝方案luogu上的其他題解都說的比較清楚了。不過根據本 注釋也許可以更好理解一些 注意 此 中行...
洛谷 1312 Mayan遊戲(dfs)
在乙個7行5列的期盤中,有至多10種顏色的方塊。當這些方塊下方空的時候,這些方塊總是會垂直掉落 當有3個顏色相同的方塊排成一行或一列時,它們會被同時消除 你需要在給定的步數內,通過調換相鄰方塊,使棋盤上沒有方塊。若做不到,輸出 1 不然輸出1種方法 要移動的方塊的x y座標 移動方向 移動方向 1 ...