題目:
https://www.luogu.org/problemnew/show/1312
早就想做了,現在才下定決心;
將近3個小時,終於做出來了;
第二個點跑了將近2s,嚇~~
只要耐心,一點點想,一遍遍調,一切皆有可能 !
準備在洛谷上發一篇題解~~~~
優化:
1.如果存在一個格子的左邊(右邊)與它相同,不移動;
2.dfs時如果遇到空格直接break;
注意:
爲保證字典序最小:
1.需要將圖翻轉90°;
2.某個格子只有在左邊什麼也沒有時才向左移動;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int ma[6][6][9];
int n;
int ans[20][20];
bool vis[20][20],Mark[20][20];
bool flag=0;
int read()//沒起到任何作用的手讀;
{
int ss=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
{
ss=ss*10+c-'0';
c=getchar();
}
return ss;
}
void swap(int &x,int &y)//交換
{
x^=y^=x^=y;
return;
}
void copy(int i)//複製
{
for(int j=0;j<7;j++)
Mark[i][j]|=vis[i][j];
return;
}
void fall(int depth)//降落;
{
for(int i=0;i<5;i++)
{
for(int j=0;j<7;j++)
{
if(!ma[depth][i][j]) continue;
int x=i,y=j;
while(y-1>=0 && !ma[depth][x][y-1] && ma[depth][x][y])
{
swap(ma[depth][x][y-1],ma[depth][x][y]);
y--;
}
}
}
return;
}
bool xiao(int depth)
{
bool f=0;
int tot=0;
memset(vis,0,sizeof(vis)),memset(Mark,0,sizeof(Mark));
for(int i=0;i<5;i++)
{
for(int j=0;j<7;j++)
{
if(Mark[i][j]) continue;
if(!ma[depth][i][j]) break;
tot=1,vis[i][j]=1;
for(int v=1;v<=5;v++)
{
if(i+v<5)
{
if(ma[depth][i][j]==ma[depth][i+v][j])//橫;
tot++,vis[i+v][j]=1;
else break;
}
}
for(int v=-1;v>=-5;v--)
{
if(i+v>=0)
{
if(ma[depth][i][j]==ma[depth][i+v][j])
tot++,vis[i+v][j]=1;
else break;
}
}
if(tot>=3)
{
copy(i);//標記消除:
f=1;//發生消除
}
memset(vis,0,sizeof(vis));//初始化;
vis[i][j]=1,tot=1;
for(int v=1;v<=7;v++)
{
if(j+v<7)
{
if(ma[depth][i][j]==ma[depth][i][j+v])//縱;
tot++,vis[i][j+v]=1;
else break;
}
}
for(int v=-1;v>=-7;v--)
{
if(j+v>=0)
{
if(ma[depth][i][j]==ma[depth][i][j+v])
tot++,vis[i][j+v]=1;
else break;
}
}
if(tot>=3)
f=1,copy(i);
memset(vis,0,sizeof(vis));
}
}
if(f)//發生過消除;
{
for(int i=0;i<5;i++)
for(int j=0;j<7;j++) if(Mark[i][j]) ma[depth][i][j]=0;
return true;
}
else return false;
}
bool check()
{
for(int i=0;i<5;i++)
if(ma[n][i][0]) return false;
return true;
}
void dfs(int depth)
{
if(depth==n+1)
{
if(!check()) return;//如果沒有消完;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=3;j++)
printf("%d ",ans[i][j]);
printf("\n");
}
exit(0);
}
memcpy(ma[depth],ma[depth-1],sizeof(ma[depth-1]));//複製過來;
for(int i=0;i<5;i++)
{
for(int j=0;j<7;j++)
{
if(!ma[depth][i][j]) break;
int dir=0;//方向;
if(!i || i==4)
{
if(i==0) dir=1;//第一列只能右移;
else if(i==4 && !ma[depth][i-1][j]) dir=-1;//最後一列只能左移;
if(ma[depth][i][j]!=ma[depth][i+dir][j])
{
ans[depth][1]=i;//儲存答案;
ans[depth][2]=j;
ans[depth][3]=dir;
swap(ma[depth][i+dir][j],ma[depth][i][j]);
do
{
fall(depth);//直到消不了爲止;
}while(xiao(depth));
dfs(depth+1);
memcpy(ma[depth],ma[depth-1],sizeof(ma[depth-1]));//回溯:
}
else continue;
}
else if(i>0 && i<4)
{
dir=1;
if(ma[depth][i][j]!=ma[depth][i+dir][j])
{
ans[depth][1]=i,ans[depth][2]=j,ans[depth][3]=dir;
swap(ma[depth][i+dir][j],ma[depth][i][j]);
do{fall(depth);}while(xiao(depth));
dfs(depth+1);
memcpy(ma[depth],ma[depth-1],sizeof(ma[depth-1]));
}
dir=-1;
if(!ma[depth][i+dir][j])
{
ans[depth][1]=i,ans[depth][2]=j,ans[depth][3]=dir;
swap(ma[depth][i+dir][j],ma[depth][i][j]);
do{fall(depth);}while(xiao(depth));
dfs(depth+1);
memcpy(ma[depth],ma[depth-1],sizeof(ma[depth-1]));
}
}
}
}
return;
}
void solve()
{
scanf("%d",&n);
for(int i=0;i<5;i++)
{
int tot=0,x;
while(true)
{
x=read();
if(!x) break;
ma[0][i][tot++]=x;
}
}
dfs(1);
cout<<"-1"<<endl;
return;
}
int main()
{
solve();
return 0;
}