题解 P1312 【Mayan游戏】
这道题,真的是调试了近一个月。。
一直得不了满分真的不爽。。
在龙神哈迪斯的建议下重构代码:于是A了
那么是什么意思呢,按照关键字顺序搜索:x,y,右,左
分为一下三个板块:移动,掉落,消除
加上剪枝:向左移相当于向右移,所以左移的时候要求左边是空的
那么这题按照这个步骤就可以A了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define RG register
using namespace std;
int n;
int a[6][8];
int ans[6][4];
void in();
void DFS(int);
void print();
int main()
{
//freopen("a.out","w",stdout);
in();
DFS(0);
printf("-1\n");
return 0;
}
inline void Diaoluo(int x)//把x这一列掉下来
{
RG int cnt1=-1;
for(RG int i=0;i<=6;i++)
if(a[x][i])a[x][++cnt1]=a[x][i];
for(RG int i=cnt1+1;i<=6;i++)a[x][i]=0;
}
inline void BOOM()//消除函数
{
RG int flag=1;
while(flag)
{
flag=0;
RG int tmp[6][8];
memcpy(tmp,a,sizeof(tmp));
//Part1 判断是否可以消除
for(RG int x=0;x<=4;x++)
{
for(RG int y=0;y<=6;y++)
{
if(x>=1&&x<=3&&tmp[x][y]&&tmp[x-1][y]==tmp[x][y]&&tmp[x+1][y]==tmp[x][y])
{
a[x-1][y]=0;
a[x][y]=0;
a[x+1][y]=0;
flag=1;
}
if(y>=1&&y<=5&&tmp[x][y]&&tmp[x][y-1]==tmp[x][y]&&tmp[x][y+1]==tmp[x][y])
{
a[x][y-1]=0;
a[x][y]=0;
a[x][y+1]=0;
flag=1;
}
}
}
if(!flag)return;
//Part2 掉下来,回到Part1
for(RG int i=0;i<=4;i++)Diaoluo(i);
}
}
inline void Update_ans(int i,int x,int y,int fangxiang)
{
ans[i][1]=x;
ans[i][2]=y;
ans[i][3]=fangxiang;
}
inline int pd_xiaowan()
{
for(RG int x=0;x<=4;x++)
for(RG int y=0;y<=6;y++)
if(a[x][y])return 0;
return 1;
}
void DFS(int step)//搜每一步
{
//Part1 判断条件
if(pd_xiaowan()&&step==n)//消除完并且步数刚好则可以
{
for(RG int i=1;i<=step;i++)
printf("%d %d %d\n",ans[i][1],ans[i][2],ans[i][3]);
exit(0);
}
if(step>=n)return;//超过规定步数
//Part2 备份
RG int tmp[6][8];
memcpy(tmp,a,sizeof(tmp));
//Part3 移动(关键字为x,y,先右再左)
for(RG int x=0;x<=4;x++)
{
for(RG int y=0;y<=6;y++)
{
if(!a[x][y])continue;//空格不能移动
if(x!=4)//没越界
{
swap(a[x][y],a[x+1][y]);
Diaoluo(x);
Diaoluo(x+1);//移动之后把这两行掉下来
BOOM();//消除
Update_ans(step+1,x,y,1);
//print();
DFS(step+1);
//回溯
Update_ans(step+1,0,0,0);
memcpy(a,tmp,sizeof(a));
}
if(x&&!a[x-1][y])
{
swap(a[x][y],a[x-1][y]);
Diaoluo(x);
Diaoluo(x-1);
BOOM();
Update_ans(step+1,x,y,-1);
//print();
DFS(step+1);
Update_ans(step+1,0,0,0);
memcpy(a,tmp,sizeof(a));
}
}
}
}
inline void in()
{
cin>>n;
for(RG int i=0;i<=4;i++)
{
RG int p=0;
do{
cin>>a[i][p];p++;
}while(a[i][p-1]!=0);
}
//print();
}
void print()
{
for(int i=0;i<=4;i++)
{
for(int j=0;j<=6;j++)printf("%d ",a[i][j]);
printf("\n");
}
printf("\n");
}
PS:我认为右移的时候相同是可以移动的,不然若没有达到规定步数,就回输出-1 如果不加会T,只能说明你的搜索不够优秀/滑稽/