闲谈:写搜索真的心累,复杂复杂.代码又长,又难调.幸好蓝书搜索并不是很短,且y总大部分都做了视频,且有辛格大佬不然我估计写不下去了.言归正传,讲讲这个题目怎么做.
题目是你可以移动且只能移动n次,使得屏幕的方块全部消掉.移动就是左移和右移,然后假如你移动方向有方块你就交换.没有方块就就掉落呗.然后消了之后也会掉落,一旦相同连续颜色的方块>=3就可以消了.答案优先级是按照x为第一关健字,y为第二关健字,1优先于-1,1表示向右移动,-1表示向左移动.
做法就是模拟上面描述的过程,搜索的剪枝有2个.
1.一旦有种方块数量<3.那么直接return false就可以了.
2.由于向右移动的优先级大于向左移动的优先级,那么一旦一个方块左边有方块且它想向左移动,是不是就等于它左边的方块向右移动呢?换句话来说,向左移动时,左边必定没有方块.
至于搜索顺序就是枚举x然后枚举y,先右移,再左移.然后我们为了方便数组,建立的是一幅倒图.
下面就是激动人心的代码时刻了.(什么时候才能到数论哎QAQ
#include <bits/stdc++.h>
using namespace std;
int n;
int an[6][8],ban[6][6][8];
bool st[6][8];
int cnt[15],bcnt[5][15];
struct node
{
int x,y,w;
}path[5];
void move(int x,int y,int mx)//处理操作.
{
swap(an[mx][y],an[x][y]);//交换.
while(true)
{
bool flag=false;
//删掉空位.
for(int i=0;i<5;i++)
{
int z=0;
for(int j=0;j<7;j++)
{
if(an[i][j])
{
an[i][z++]=an[i][j];
}
}
while(z<7) an[i][z++]=0;
}
//标记要删除的地方
memset(st,false,sizeof st);
for(int i=0;i<5;i++)//枚举所有点.
{
for(int j=0;j<7;j++)
{
if(an[i][j])
{
int l,r;
l=r=i;
while(l-1>=0&&an[l][j]==an[l-1][j]) l--;
while(r+1<5&&an[r][j]==an[r+1][j]) r++;
if(r-l+1>=3) {flag=true;st[i][j]=true;}
else
{
l=r=j;
while(l-1>=0&&an[i][l]==an[i][l-1]) l--;
while(r+1<7&&an[i][r]==an[i][r+1]) r++;
if(r-l+1>=3) {flag=true;st[i][j]=true;}
}
}
}
}
//删除标记的地方.
if(flag)
{
for(int i=0;i<5;i++)
{
for(int j=0;j<7;j++)
{
if(st[i][j])
{
cnt[0]--;
cnt[an[i][j]]--;
an[i][j]=0;
}
}
}
}
else break;
}
}
bool dfs(int u)//处理枚举.
{
if(u==n)//假如我已经操作了n次,那么判断下是不是屏幕清0了.
{
return (!cnt[0]);
}
for(int i=1;i<=10;i++)
{
if(cnt[i]==1||cnt[i]==2) return false;
}//剪枝1.
memcpy(ban[u],an,sizeof ban[u]);
memcpy(bcnt[u],cnt,sizeof cnt);
for(int x=0;x<5;x++)//先枚举x坐标
{
for(int y=0;y<7;y++)//再枚举y坐标
{
if(an[x][y])//能移动的前提是这个位子上有方块.
{
int mx=x+1;//向右移动.
if(mx<5)//只有<5就可以交换
{
move(x,y,mx);
path[u]={x,y,1};
if(dfs(u+1)) return true;
memcpy(an,ban[u],sizeof ban[u]);
memcpy(cnt,bcnt[u],sizeof cnt);
}
mx=x-1;//向左移动.
if(mx>=0&&!an[mx][y])
{
move(x,y,mx);
path[u]={x,y,-1};
if(dfs(u+1)) return true;
memcpy(an,ban[u],sizeof ban[u]);
memcpy(cnt,bcnt[u],sizeof cnt);
}
}
}
}
return false;//假如都不成功就返回false
}
int main()//处理输入输出
{
cin>>n;
for(int i=0;i<5;i++)
{
int t=0,x;
while(cin>>x,x) {an[i][t++]=x;cnt[0]++;cnt[x]++;}
}//处理输入
if(dfs(0))
{
for(int i=0;i<n;i++) cout<<path[i].x<<' '<<path[i].y<<' '<<path[i].w<<endl;
}
else puts("-1");
return 0;
}
京公网安备 11010502036488号