题目描述
给个链接门..........
https://www.luogu.org/problem/show?pid=1312#sub
解释:
两次A的题目,就是妥妥暴力
判断点是否存在,存在就换着试试。。
优化的剪枝:如果和右边(下面)颜色不一样就换走,如果左边(上面)是空的就换走
说说一开始犯的zz的错误。
1.降落时可以降落好多格【捂脸】
2.拷贝的b数组应该用局部变量。如果是全局变量,复原过程就不再正确
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int a[5][7],x[10],y[10],z[10];
bool ff=false;
int n,m;
int xc()
{
int i,j;
bool dis[5][7];
memset(dis,0,sizeof(dis));
for (i=0;i<=4;i++)//降落
for (j=1;j<=6;j++)
if (a[i][j])
{
int k=1;
while (k<=j && a[i][j-k]==0) swap(a[i][j-k],a[i][j-k+1]),k++;
}
for (i=0;i<=4;i++)//消除过程
for (j=0;j<=6;j++)
if (a[i][j])
{
if (i<3 && a[i][j]==a[i+1][j] && a[i][j]==a[i+2][j])
{
dis[i][j]=true; dis[i+1][j]=true; dis[i+2][j]=true;
int k=i+2;
while (k<4 && a[k][j]==a[k+1][j])
dis[++k][j]=true;
}
if (j<5 && a[i][j]==a[i][j+1] && a[i][j]==a[i][j+2])
{
dis[i][j]=true; dis[i][j+1]=true; dis[i][j+2]=true;
int k=j+2;
while (k<6 && a[i][j]==a[i][k+1])
dis[i][++k]=true;
}
}
int rr=0;
for (i=0;i<=4;i++)
for (j=0;j<=6;j++)
if (dis[i][j]) a[i][j]=0,rr++;
if (rr==0) return rr;
rr+=xc();
return rr;
}
void dfs(int t,int yu)
{
int b[5][7];
if (ff) return;
int i,j;
if (t>n)
{
if (!yu)
{
for (i=1;i<=n;i++)
printf("%d %d %d\n",x[i],y[i],z[i]);
ff=true;
}
return;
}
for (i=0;i<=4;i++)//拷贝
for (j=0;j<=6;j++)
b[i][j]=a[i][j];
for (i=0;i<=4;i++)
for (j=0;j<=6;j++)
if (a[i][j])
{
bool flag=true;
x[t]=i; y[t]=j;
if (i<4 && a[i][j]!=a[i+1][j])
{
z[t]=1;
swap(a[i][j],a[i+1][j]);
int now=yu-xc();
dfs(t+1,now);
flag=false;
}
if (!flag)
{
for (int ii=0;ii<=4;ii++)//复原
for (int jj=0;jj<=6;jj++)
a[ii][jj]=b[ii][jj];
flag=true;
}
if (i && !a[i-1][j])
{
z[t]=-1;
swap(a[i][j],a[i-1][j]);
int now=yu-xc();
dfs(t+1,now);
flag=false;
}
if (!flag)
{
for (int ii=0;ii<=4;ii++)//复原
for (int jj=0;jj<=6;jj++)
a[ii][jj]=b[ii][jj];
flag=true;
}
}
}
int main()
{
int i,j;
scanf("%d",&n);
for (i=0;i<=4;i++)
for (j=0;j<=7;j++)
{
scanf("%d",&a[i][j]);
if (a[i][j]) m++;
else break;
}
dfs(1,m);
if (!ff) printf("-1");
}