ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Luogu-P2324-[SCOI2005]骑士精神

2019-02-04 16:44:23  阅读:304  来源: 互联网

标签:sy maxstep int Luogu register DFS sx P2324 SCOI2005


【题面】

题目描述:

输入输出格式:

输入格式:

第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

输出格式:

对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

输入输出样例:

Input:

2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100

Output:

7
-1

说明:

【题解】:

P.S.:这题并不是此时完成的,但思路仍是可贵的,记录下来,何乐而不为?

首先确定——DFS深搜。

然而,我们很快就发现了:DFS没有明显的深度!!!,这样的解答树是极大的(将近于枚举棋盘的全排列)。

这时,我们将不得不转变思路:IDDFS迭代加深

注:下面代码中的DFS(sx,sy,0)bool类型的

熟练敲框架(框架!??):

for(maxstep=0;!DFS(sx,sy,0)&&maxstep<15;maxstep++);
bool DFS(int x,int y,int step)
{
    if(is_finished())
    {
        is_solved=1; 
        return 1;
    }
    if(step>=maxstep)return 0;
    for(register int i=1;i<=8;i++)
    {
        if(x+dx[i]>5||x+dx[i]<1||y+dy[i]>5||y+dy[i]<1)continue;
        x+=dx[i],y+=dy[i];
        swap(now[x][y],now[x-dx[i]][y-dy[i]]);
        if(DFS(x,y,step+1))
        {
            swap(now[x][y],now[x-dx[i]][y-dy[i]]);
            return 1;
        }
        swap(now[x][y],now[x-dx[i]][y-dy[i]]);
        x-=dx[i],y-=dy[i];
    }
    return 0;
}

好吧也不算太难。。。

HOWEVER——

过不了。泼冷水(谁裸迭代加深过了我给他\(10^{10^{10}}\%1RMB\))

优化??

LevelUp!——\(IDA*\)

也就是\(A*\)优化的迭代加深。

简单的来说就是:如果当前步数+理想状态(calc估价函数)都无法在maxstep步内到达目标,即剪枝。

那么估价函数怎么设定?

别急,一个一个来。

在目标棋盘上,如果一个骑士不在自己的位置上(即黑白不对应),那么这一步是一定要走的。

那么,calc()的设定方式是显而易见了:

inline int calc()
{
    register int i,j,count=0;
    for(i=1;i<=5;i++)
        for(j=1;j<=5;j++)
            if(now[i][j]!=goal[i][j]&&now[i][j]!='*'&&goal[i][j]!='*')count++;
    return count;
}

好了,放CODE:

#include<iostream>
using namespace std;

const int dx[9]={0,-2,-1,1,2,2,1,-1,-2};
const int dy[9]={0,1,2,2,1,-1,-2,-2,-1};
const char goal[6][6]={{0},{0,'1','1','1','1','1'},{0,'0','1','1','1','1'},{0,'0','0','*','1','1'},{0,'0','0','0','0','1'},{0,'0','0','0','0','0'}};
char now[6][6];
bool is_solved;
int maxstep;

inline bool is_finished()
{
    register int i,j;
    for(i=1;i<=5;i++)
        for(j=1;j<=5;j++)
            if(goal[i][j]!=now[i][j])return 0;
    return 1;
}

inline int calc()
{
    register int i,j,count=0;
    for(i=1;i<=5;i++)
        for(j=1;j<=5;j++)
            if(now[i][j]!=goal[i][j]&&now[i][j]!='*'&&goal[i][j]!='*')count++;
    return count;
}

bool DFS(int x,int y,int step)
{
    if(is_finished())
    {
        is_solved=1; 
        return 1;
    }
    if(step>=maxstep||step+calc()>maxstep)return 0;
    for(register int i=1;i<=8;i++)
    {
        if(x+dx[i]>5||x+dx[i]<1||y+dy[i]>5||y+dy[i]<1)continue;
        x+=dx[i],y+=dy[i];
        swap(now[x][y],now[x-dx[i]][y-dy[i]]);
        if(DFS(x,y,step+1))
        {
            swap(now[x][y],now[x-dx[i]][y-dy[i]]);
            return 1;
        }
        swap(now[x][y],now[x-dx[i]][y-dy[i]]);
        x-=dx[i],y-=dy[i];
    }
    return 0;
}

signed main()
{
    int T;cin>>T;
    while(T--)
    {
        is_solved=0;
        register int i,j;
        int sx,sy;
        for(i=1;i<=5;i++)
            for(j=1;j<=5;j++)
            {
                cin>>now[i][j];
                if(now[i][j]=='*')sx=i,sy=j;
            }
        for(maxstep=0;!DFS(sx,sy,0)&&maxstep<15;maxstep++);
        if(!is_solved)cout<<"-1"<<endl;
        else cout<<maxstep<<endl;
    }
    return 0;
}

标签:sy,maxstep,int,Luogu,register,DFS,sx,P2324,SCOI2005
来源: https://www.cnblogs.com/-Wallace-/p/10351788.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有