洛谷 P1312 [ NOIP 2011 ] Mayan游戏 —— 搜索+模拟

题目:https://www.luogu.org/problemnew/show/P1312

还是不擅长这种题,所以参考了一下TJ;

其实也很好搜,按字典序,先搜右移,再搜左移;

不交换相同颜色的两个格子,因为浪费;

左移就不交换了,避免重复,只有左边为空时左移;

写个处理下落的 fall 函数,再写个处理消格子的 refresh 函数(其中用到了 fall ),就可以方便地搜索了!

我存的是行和列,所以和坐标正好相反,一定要注意字典序的处理!

优美。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,mp[10][10][10],ansx[10],ansy[10],ansm[10];
bool vis[10][10];
void fall(int s)
{
    for(int j=1,sz;j<=5;j++)
    {
        sz=0;
        for(int i=1;i<=7;i++)
            if(mp[s][i][j])mp[s][++sz][j]=mp[s][i][j];
        while(sz<7)mp[s][++sz][j]=0;//
    }
}
void refresh(int s)
{
    bool fl=0;
    while(1)
    {
        fl=0; fall(s);
        for(int i=1;i<=7;i++)
            for(int j=1;j<=5;j++)
            {
                if(!mp[s][i][j])continue;//
                if(i<=5&&mp[s][i][j]==mp[s][i+1][j]&&mp[s][i][j]==mp[s][i+2][j])
                {
                    fl=1;
                    vis[i][j]=vis[i+1][j]=vis[i+2][j]=1;
                }
                if(j<=3&&mp[s][i][j]==mp[s][i][j+1]&&mp[s][i][j]==mp[s][i][j+2])
                {
                    fl=1;
                    vis[i][j]=vis[i][j+1]=vis[i][j+2]=1;
                }
            }
        if(!fl)break;
        for(int i=1;i<=7;i++)
            for(int j=1;j<=5;j++)
                if(vis[i][j])mp[s][i][j]=0,vis[i][j]=0;
    }
}
bool dfs(int s)
{
    for(int i=1;i<=7;i++)
        for(int j=1;j<=5;j++)mp[s][i][j]=mp[s-1][i][j];
    refresh(s);
    if(s>n)
    {
        for(int j=1;j<=5;j++)
            if(mp[s][1][j])return 0;
        return 1;
    }
    for(int j=1;j<=5;j++)//字典序! 
        for(int i=1;i<=7;i++)    if(mp[s][i][j])
        {
            if(j<5&&mp[s][i][j]!=mp[s][i][j+1])//1
            {
                ansx[s]=i; ansy[s]=j; ansm[s]=1;
                swap(mp[s][i][j],mp[s][i][j+1]);
                if(dfs(s+1))return 1;
                swap(mp[s][i][j],mp[s][i][j+1]);
            }
            if(j>1&&!mp[s][i][j-1])//-1
            {
                ansx[s]=i; ansy[s]=j; ansm[s]=-1;
                swap(mp[s][i][j],mp[s][i][j-1]);
                if(dfs(s+1))return 1;
                swap(mp[s][i][j],mp[s][i][j-1]);
            }
        }
    return 0;
}
int main()
{
    scanf("%d",&n);
    for(int j=1;j<=5;j++)
        for(int i=1,x;i<=8;i++)
        {
            scanf("%d",&x); if(!x)break;
            mp[0][i][j]=x;
        }
    if(dfs(1))//1
    {
        for(int i=1;i<=n;i++)
            printf("%d %d %d
",ansy[i]-1,ansx[i]-1,ansm[i]);//坐标! 
    }
    else printf("-1
");
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/9403666.html