洛谷 1312 [NOIP2011] Mayan游戏 dfs+模拟

来源:互联网 发布:西安网络写手招聘 编辑:程序博客网 时间:2024/06/11 22:12

题目:
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;}