#算法/进阶搜索
思路:
根据题意,我们可以知道,这题只能枚举,剪枝,因此,我们考虑如何枚举,剪枝.
首先,我们要定义下降函数down(),使得小木块右移时,能够下降到最低处,其次,我们还需要写出判断函数,判断矩阵内是否有小木块没被消除.另外,我们还需要消除函数,将矩阵内三个相连的小木块清除,dfs()函数进行搜索
这里,我们定义数组横坐标代表原矩阵的列,纵坐标代表原矩阵的行,坐标轴从1,1开始
check判断函数:
直接判断当前矩阵中是否仍存在小正方行
cpp
bool check(){
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(dp[i][j])return false;
}
}
return true;
}
clear()清除函数
cpp
由于我们后序每次将正方行下降后都需要判断当前是否需要清除,所以我们将clear定义为int,
判断的时候,我们三个一组的判断
1.先横向判断每一行是否有三个连续的
2.在竖向判断是否有三个连续的
注意:这里我们全部判断完后再进行删除,否则会出现4-5个连续的同色方块只能删除三个
int clear(){
int g=0;
int del[10][10]={0};
横向删除
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(!dp[i][j])continue;
if(i>1&&i<5){
if(dp[i-1][j]==dp[i][j]&&dp[i][j]==dp[i+1][j]){
del[i-1][j]=del[i][j]=del[i+1][j]=g=1;
}
}
}
}
竖向删除
for(int i=1;i<=5;i++){
for(int j=2;j<=6;j++){
if(dp[i][j]==0)continue;
if(dp[i][j-1]==dp[i][j]&&dp[i][j]==dp[i][j+1]){
del[i][j-1]=del[i][j]=del[i][j+1]=g=1;
}
}
}
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(del[i][j]==1)dp[i][j]=0;
}
}
return g;
}
down()下降函数
cpp
在下降的时候,会出现一列的小正方形多组不连续,比如1020201,我们在下降的时候需要先将第一个2下降到最底部,再将第二个2下降到最底部,最后将1下降到最底部,所以,我们从下往上降
void down(){
for(int i=1;i<=5;i++){
从原矩阵第二行开始下降
for(int j=2;j<=7;j++){
if(dp[i][j]==0)continue;
int k=j;
这里一定要添加限定条件k-1>=1
while(k-1>=1&&dp[i][k-1]==0){
swap(dp[i][k],dp[i][k-1]);
k--;
}
}
}
}
dfs()函数
定义flag代表我们是否找到可删除合法方案
cpp
void dfs(int x){
如果已经删除完了,直接返回
if(flag)return;
if(x>n){
if(check()){
for(int i=1;i<=n;i++){
res,0放原坐标轴x,1放原坐标y,2放正方向移动方向
cout<<res[i][0]<<' '<<res[i][1]<<' '<<res[i][2]<<endl;
}
flag=true;
}
return;
}
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(dp[i][j]==0)continue;
int tmp[10][10];
保存初始状态
memcpy(tmp,dp,sizeof(tmp));
正方行右移
if(i<5){
res[x][0]=i-1;
res[x][1]=j-1;
res[x][2]=1;
swap(dp[i][j],dp[i+1][j]);
for(down();clear()!=0;down());
dfs(x+1);
恢复初始状态
memcpy(dp,tmp,sizeof(dp));
}
正方向左移
if(i>=2){
res[x][0]=i-1;
res[x][1]=j-1;
res[x][2]=-1;
swap(dp[i][j],dp[i-1][j]);
for(down();clear()!=0;down());
dfs(x+1);
恢复初始状态
memcpy(dp,tmp,sizeof(dp));
}
}
}
}
完整代码
cpp
#include<iostream>
#include<cstring>
using namespace std;
int n;
int dp[10][10];
int res[30][3];
bool flag=false;
bool check(){
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(dp[i][j])return false;
}
}
return true;
}
int clear(){
int g=0;
int del[10][10]={0};
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(!dp[i][j])continue;
if(i>1&&i<5){
if(dp[i-1][j]==dp[i][j]&&dp[i][j]==dp[i+1][j]){
del[i-1][j]=del[i][j]=del[i+1][j]=g=1;
}
}
}
}
for(int i=1;i<=5;i++){
for(int j=2;j<=6;j++){
if(dp[i][j]==0)continue;
if(dp[i][j-1]==dp[i][j]&&dp[i][j]==dp[i][j+1]){
del[i][j-1]=del[i][j]=del[i][j+1]=g=1;
}
}
}
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(del[i][j]==1)dp[i][j]=0;
}
}
return g;
}
void down(){
for(int i=1;i<=5;i++){
for(int j=2;j<=7;j++){
if(dp[i][j]==0)continue;
int k=j;
while(k-1>=1&&dp[i][k-1]==0){
swap(dp[i][k],dp[i][k-1]);
k--;
}
}
}
}
void dfs(int x){
if(flag)return;
if(x>n){
if(check()){
for(int i=1;i<=n;i++){
cout<<res[i][0]<<' '<<res[i][1]<<' '<<res[i][2]<<endl;
}
flag=true;
}
return;
}
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(dp[i][j]==0)continue;
int tmp[10][10];
memcpy(tmp,dp,sizeof(tmp));
if(i<5){
res[x][0]=i-1;
res[x][1]=j-1;
res[x][2]=1;
swap(dp[i][j],dp[i+1][j]);
for(down();clear()!=0;down());
dfs(x+1);
memcpy(dp,tmp,sizeof(dp));
}
if(i>=2){
res[x][0]=i-1;
res[x][1]=j-1;
res[x][2]=-1;
swap(dp[i][j],dp[i-1][j]);
for(down();clear()!=0;down());
dfs(x+1);
memcpy(dp,tmp,sizeof(dp));
}
}
}
}
int main(void){
cin>>n;
for(int i=1;i<=5;i++){
int cnt=1;
int tmp;
while(cin>>tmp&&tmp){
dp[i][cnt]=tmp;
cnt++;
}
}
dfs(1);
if(flag==false){
cout<<-1<<endl;
}
return 0;
}