闲谈:写搜索真的心累,复杂复杂.代码又长,又难调.幸好蓝书搜索并不是很短,且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; }