10274 - Fans and Gems

描述:这道题更让人头疼,想破头才知道移动的顺序必须按照字母的顺序,就是得按照D、L、R、U这个顺寻才能过,哪有这么坑人的啊,无语了……
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define NX 1000003
int N,M,flag;
char d[]= {'D','L','R','U'};
int next[NX],head[NX];
char str[NX][14][22],s[1000];
int count[NX][3];
int move[4][2]= {{0,-1},{0,1},{1,0},{-1,0}};
void search(int c,int x,int y,int rear)
{
    if(str[rear][x][y]==c) str[rear][x][y]=' ';
    else return;
    search(c,x+1,y,rear);
    search(c,x,y+1,rear);
    search(c,x-1,y,rear);
    search(c,x,y-1,rear);
}
int hash(int rear)
{
    int c=0;
    for(int i=0; i<N; i++)
        for(int j=0; j<M; j++)
            if(str[rear][i][j]>='1'&&str[rear][i][j]<='3') c=(c*5+str[rear][i][j]-'0')%NX;
            else if(str[rear][i][j]==' ') c=(c*5)%NX;
            else if(str[rear][i][j]=='@') c=(c*5+4)%NX;
    return c;
}
bool insert(int c,int rear)
{
    int x=head[c];
    while(x!=-1)
    {
        if(memcmp(str[x],str[rear],sizeof(str[rear]))==0) return false;
        x=next[x];
    }
    next[rear]=head[c];
    head[c]=rear;
    return true;
}
void show(int front)
{
    if(front) show(count[front][0]);
    else return;
    printf("%c",d[count[front][1]]);
}
void del(int rear,int i)
{
    flag=0;
    for(int j=1; j<N-1; j++)
        for(int k=1; k<M-1; k++)
            if(str[rear][j][k]>='1'&&str[rear][j][k]<='3')
            {
                int c=0;
                for(int l=0; l<4; l++)
                {
                    int x=move[l][0]+j,y=move[l][1]+k;
                    if(str[rear][x][y]==str[rear][j][k]) c=flag=1;
                }
                if(c) search(str[rear][j][k],j,k,rear);
            }
}
void bfs()
{
    flag=0;
    int rear=1,front=0;
    while(rear>front&&rear<NX)
    {
        flag=0;
        for(int i=1; i<N-1&&!flag; i++)
            for(int j=1; j<M-1&&!flag; j++)
                if(str[front][i][j]>='1'&&str[front][i][j]<='3') flag++;
        if(!flag)
        {
            show(front);
            printf("\n");
            flag=1;
            return;
        }
        flag=0;
        if(count[front][2]<18) for(int i=0; i<4; i++)
            {
                for(int j=0; j<N; j++)
                    for(int k=0; k<M; k++)
                        str[rear][j][k]=str[front][j][k];
                flag=0;
                if(i==1) while(1)
                    {
                        for(int j=1; j<N-1; j++)
                            for(int k=1; k<M-1; k++)
                                if(str[rear][j][k]==' ')
                                {
                                    int l=k+1;
                                    while( l<M-1&&str[rear][j][l]==' ' )l++;
                                    if((str[rear][j][l]>='1'&&str[rear][j][l]<='3')||str[rear][j][l]=='@')
                                    {
                                        flag=1;
                                        str[rear][j][k]=str[rear][j][l];
                                        str[rear][j][l]=' ';
                                    }
                                    else k=l;
                                }
                        if(flag)
                        {
                            del(rear,i);
                            if(!flag) break;
                        }
                        else break;
                    }
                else if(i==3) while(1)
                    {
                        for(int k=1; k<M-1; k++)
                            for(int j=1; j<N-1; j++)
                                if(str[rear][j][k]==' ')
                                {
                                    int l=j+1;
                                    while(l<N-1&&str[rear][l][k]==' ' )l++;
                                    if((str[rear][l][k]>='1'&&str[rear][l][k]<='3')||str[rear][l][k]=='@')
                                    {
                                        flag=1;
                                        str[rear][j][k]=str[rear][l][k];
                                        str[rear][l][k]=' ';
                                    }
                                    else j=l;
                                }
                        if(flag)
                        {
                            del(rear,i);
                            if(!flag) break;
                        }
                        else break;
                    }
                else if(i==2) while(1)
                    {
                        for(int j=1; j<N-1; j++)
                            for(int k=M-2; k>0; k--)
                                if(str[rear][j][k]==' ')
                                {
                                    int l=k-1;
                                    while(l>0&&str[rear][j][l]==' ' )l--;
                                    if((str[rear][j][l]>='1'&&str[rear][j][l]<='3')||str[rear][j][l]=='@')
                                    {
                                        flag=1;
                                        str[rear][j][k]=str[rear][j][l];
                                        str[rear][j][l]=' ';
                                    }
                                    else k=l;
                                }
                        if(flag)
                        {
                            del(rear,i);
                            if(!flag) break;
                        }
                        else break;
                    }
                else while(1)
                    {
                        for(int k=1; k<M-1; k++)
                            for(int j=N-2; j>0; j--)
                                if(str[rear][j][k]==' ')
                                {
                                    int l=j-1;
                                    while( l>0&&str[rear][l][k]==' ') l--;
                                    if((str[rear][l][k]>='1'&&str[rear][l][k]<='3')||str[rear][l][k]=='@')
                                    {
                                        flag=1;
                                        str[rear][j][k]=str[rear][l][k];
                                        str[rear][l][k]=' ';
                                    }
                                    else j=l;
                                }
                        if(flag)
                        {
                            del(rear,i);
                            if(!flag) break;
                        }
                        else break;
                    }
                int c=hash(rear);
                if(insert(c,rear))
                {
                    count[rear][0]=front;
                    count[rear][1]=i;
                    count[rear][2]=count[front][2]+1;
                    rear++;
                }
            }
        front++;
    }
}
int main()
{
    //freopen("a.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&N,&M);
        getchar();
        for(int i=0; i<N; i++)
            gets(str[0][i]);
        memset(next,-1,sizeof(next));
        memset(head,-1,sizeof(head));
        memset(count,0,sizeof(count));
        int c=hash(0);
        insert(c,0);
        bfs();
        if(!flag) printf("-1\n");
        gets(s);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值