题解 P1312 【Mayan游戏】
因为没有实名验证,发不了讨论,所以索性发一篇题解。由于自己在这道题上卡了2天,所以犯了各种各样的错误。
首先讲思路,其实和楼下差不多,就是可以换就换,剪枝掉左右一样的,在左面但是已经有块的(因为已经换过了)。
全wa自然不用说,回去重改。只拿10分的,看看自己的消除板块是否有问题。
20分的,看看自己的x轴和y轴是否颠倒。
最重要的地方来了,如果你有5个TLE!!那么你犯了一个可能一星期都查不出来的错误!!那就是最后的判断过程,代码给注释。
在测数据时,如果你也用dev c++如果程序没结果不一定是出错,可以等一等。。。。。。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define in(x) x=read()
int a[10][10];
int read(){
int num=0;
char c;
int flag=1;
while((c=getchar())==' '||c=='\n'||c=='\r');
if(c=='-')flag=-1;
else num=c-'0';
while(isdigit(c=getchar()))num=num*10+(c-'0');
return num;
}//由于数据过小,其实没必要读入优化
int n;
int ans1[20],ans2[20],ans3[20];//方向 x y
int cnt=0;
void remove(){
for (int i=1;i<=5;++i)
for (int j=1;j<=7;++j)
{
int x=i,y=j;
while (a[x][y]!=0&&a[x][y-1]==0&&y-1>=1)
{
swap(a[x][y],a[x][y-1]);
--y;
}
}//降下来!
int flag=1;
int c[10][10];
// memset(c,0,sizeof(c));另类的储存方法
//for(int ii=1;ii<=5;ii++)
// for(int jj=1;jj<=7;jj++)
//c[ii][jj]=a[ii][jj];
memcpy(c,a,sizeof(c));//我们储存一个备份,如果不储存就要另判4个及以上的块
for(int i=1;i<=5;i++)
for(int j=1;j<=7;j++){
if(c[i][j]){//如果是第四个,那么前面的只是重复的赋了一个0,如果不储存备份,由于a已经修改,第四个就不会被判出
if(c[i][j+1]==c[i][j]&&c[i][j-1]==c[i][j]){
a[i][j]=0;
a[i][j-1]=0;
a[i][j+1]=0;
flag=0;
}
if(c[i][j]==c[i-1][j]&&c[i][j]==c[i+1][j]){//这个是相当于是x轴的 消除
a[i][j]=0;
a[i-1][j]=0;
a[i+1][j]=0;
flag=0;
}
}
}
if(!flag)
remove();//消除了以后,自然还会有再次需要消除的块
}
bool judge(){//消除
bool flag=1;
for(int i=1;i<=5;i++){
if(a[i][1])flag=false;
}
return flag;
}
bool dfs(int step){
if(step>n){
return 0;
}
if(step==n){
//这里是最重要的地方,如果你写的是if(setp==n&&judge())那你的不可行的解就会多走一边!
if(judge())return 1;
return 0;
}
int b[10][10];
memcpy(b,a,sizeof(b));
for(int i=1;i<=5;i++){
for(int j=1;j<=7;j++){
if(a[i][j]){
if(i!=5&&a[i][j]!=a[i+1][j]){//边界,以及同颜色 向右走
swap(a[i][j],a[i+1][j]);
remove();
if(dfs(step+1)){//我的代码是有回溯的,也可以没有回溯过程,直接输出,但是我觉得这样更好理解;
ans1[++cnt]=1;
ans2[cnt]=i-1;
ans3[cnt]=j-1;
return 1;
}
memcpy(a,b,sizeof(a));
//vis1[i]=0;
}
if(i!=1&&a[i-1][j]==0){//左走
swap(a[i][j],a[i-1][j]);
remove();
if(dfs(step+1)){
ans1[++cnt]=-1;
ans2[cnt]=i-1;
ans3[cnt]=j-1;
return 1;
}
memcpy(a,b,sizeof(a));
}
}
}
}
return 0;
}
int main(){
in(n);
memset(a,0,sizeof(a));
for(int i=1;i<=5;i++){
int x;
in(x);
int j=1;
while(x){
a[i][j++]=x;
in(x);
}
} dfs(0);
for(int i=cnt;i>=1;i--){
printf("%d %d %d\n",ans2[i],ans3[i],ans1[i]);//回溯过程是自低向上,所以要倒着输出
}
if(cnt==0)printf("-1");
}