【搜索】[NOIP2012]mayan游戏
题目自己上网找。
分析,由于只有五层,而且每一层的选择很多,所以总的状态十分多,果断dfs。
暴搜过70%数据。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,a[6][6][9],ans[6][3],dir[2]={-1,1};
bool f[6][6][9];
bool clear(int i){
int j,k;
bool flag=0;
for(j=1;j<=5;j++)
for(k=1;a[i][j][k];k++){
if(a[i][j][k]==a[i][j][k-1]&&a[i][j][k]==a[i][j][k+1])
f[i][j][k]=f[i][j][k-1]=f[i][j][k+1]=1,flag=1;
if(a[i][j][k]==a[i][j-1][k]&&a[i][j+1][k]==a[i][j][k])
f[i][j][k]=f[i][j-1][k]=f[i][j+1][k]=1,flag=1;
}
for(j=1;j<=5;j++)
for(k=1;a[i][j][k];k++)
if(f[i][j][k])
a[i][j][k]=0,f[i][j][k]=0;
return flag;
}
bool drop(int i){
int j,k,l;
bool flag=0;
for(j=1;j<=5;j++){
for(k=7;!a[i][j][k];k--);
for(;k>0;k--)
if(!a[i][j][k]){
for(flag=1,l=k+1;a[i][j][l];l++)
a[i][j][l-1]=a[i][j][l];
a[i][j][l-1]=a[i][j][l];
}
}
return flag;
}
bool check(){
for(int i=1;i<=5;i++)
if(a[n][i][1])
return 0;
return 1;
}
void print(){
for(int i=1;i<=n;i++)
printf("%d %d %d\n",ans[i][0]-1,ans[i][1]-1,ans[i][2]);
}
void dfs(int i){
if(i>n){
if(check()){
print();
exit(0);
}
return;
}
int j,k,d,tj;
for(j=1;j<=5;j++)
for(k=1;a[i-1][j][k];k++)
for(d=0;d<2;d++){
memcpy(a[i],a[i-1],sizeof a[i]);
tj=j+dir[d];
if(!tj||tj>5)
continue;
swap(a[i][j][k],a[i][tj][k]);
ans[i][0]=j,ans[i][1]=k,ans[i][2]=dir[d];
while(drop(i)||clear(i));
dfs(i+1);
}
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=1;i<=5;i++)
for(j=1;;j++){
scanf("%d",&a[0][i][j]);
if(!a[0][i][j])
break;
}
dfs(1);
puts("-1");
}
加上一个小小的剪枝,就AC了
如果相邻的两个格子都不是空的,我们只考虑向右移动。
如果左边的格子是空的,再考虑向左移动。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,a[6][6][9],ans[6][3];
bool f[6][6][9];
bool clear(int i){
int j,k;
bool flag=0;
for(j=1;j<=5;j++)
for(k=1;a[i][j][k];k++){
if(a[i][j][k]==a[i][j][k-1]&&a[i][j][k]==a[i][j][k+1])
f[i][j][k]=f[i][j][k-1]=f[i][j][k+1]=1,flag=1;
if(a[i][j][k]==a[i][j-1][k]&&a[i][j+1][k]==a[i][j][k])
f[i][j][k]=f[i][j-1][k]=f[i][j+1][k]=1,flag=1;
}
for(j=1;j<=5;j++)
for(k=1;a[i][j][k];k++)
if(f[i][j][k])
a[i][j][k]=0,f[i][j][k]=0;
return flag;
}
bool drop(int i){
int j,k,l;
bool flag=0;
for(j=1;j<=5;j++){
for(k=7;!a[i][j][k];k--);
for(;k>0;k--)
if(!a[i][j][k]){
for(flag=1,l=k+1;a[i][j][l];l++)
a[i][j][l-1]=a[i][j][l];
a[i][j][l-1]=a[i][j][l];
}
}
return flag;
}
bool check(){
for(int i=1;i<=5;i++)
if(a[n][i][1])
return 0;
return 1;
}
void print(){
for(int i=1;i<=n;i++)
printf("%d %d %d\n",ans[i][0]-1,ans[i][1]-1,ans[i][2]);
}
void dfs(int i){
if(i>n){
if(check()){
print();
exit(0);
}
return;
}
int j,k,tj;
for(j=1;j<=5;j++)
for(k=1;a[i-1][j][k];k++){
memcpy(a[i],a[i-1],sizeof a[i]);
tj=j+1;
if(tj<=5){
swap(a[i][j][k],a[i][tj][k]);
ans[i][0]=j,ans[i][1]=k,ans[i][2]=1;
while(drop(i)||clear(i));
dfs(i+1);
}
memcpy(a[i],a[i-1],sizeof a[i]);
tj=j-1;
if(tj&&!a[i][tj][k]){
ans[i][0]=j,ans[i][1]=k,ans[i][2]=-1;
swap(a[i][j][k],a[i][tj][k]);
while(drop(i)||clear(i));
dfs(i+1);
}
}
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=1;i<=5;i++)
for(j=1;;j++){
scanf("%d",&a[0][i][j]);
if(!a[0][i][j])
break;
}
dfs(1);
puts("-1");
}