zoukankan      html  css  js  c++  java
  • [SCOI2005]骑士精神(IDA*)

    题面:[SCOI2005]骑士精神

    对于这道题,我们第一眼:(bfs)爆搜

    第二眼:发现事情没这么简单:这是道省选题

    第三眼:仔细一想,直接(bfs)难道不会被卡爆吗??

    第四眼:发现题目中有:“如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1

    好的,(IDA)*:启发式迭代加深

    (IDA)*是什么?

    其实就是在(A)*的基础上加上迭代加深

    还不知道(A)*的同学点这里

    迭代加深其实就是每次搜索的时候限制你的搜索深度,使你的搜索树的深度保持在一个较为合理的地方,使你的时间不会爆炸,这样就可以使你在全局搜索的深度很大而答案深度很小的情况下(也是使用(IDA)*的条件)快速得出答案

    在这道题中,明显可以看出,答案深度(<=15),所以我们考虑使用(IDA)*,在每次搜索是加上限制深度条件(maxstep),如果当前搜索深度(step==maxstep),就返回答案

    作为(A)*的精髓,估价函数(g(x))当然是我们思考的主要对象

    我们可以发现,这道题给出了棋盘的目标布局

    我们可以每次(dfs)将要进入下一层时,我们都对下一层的棋盘和目标棋盘进行对比,如果差异值(tot+step>maxstep),那么我们就不进入下一层

    详见代码

    #include<bits/stdc++.h>
    using namespace std;
    const int nextx[8]={1,2,2,1,-1,-2,-2,-1};
    const int nexty[8]={-2,-1,1,2,2,1,-1,-2};
    //目标棋盘
    int goal[7][7]={
    	{0,0,0,0,0,0},
    	{0,1,1,1,1,1},
    	{0,0,1,1,1,1},
    	{0,0,0,2,1,1},
    	{0,0,0,0,0,1},
    	{0,0,0,0,0,0}
    };
    char ch[6][6];
    int num[6][6];
    bool flag=0;
    int diff()//差异值
    {
    	int tot=0;
    	for(int i=1;i<=5;i++)
    	{
    		for(int j=1;j<=5;j++)
    		{
    			if(num[i][j]!=goal[i][j])tot++;
    		}
    	}
    	return tot;
    }
    bool check(int x,int y)
    {
    	return x>5||x<1||y>5||y<1;
    }
    void dfs(int step,int x,int y,int maxstep)
    {
    	if(flag)return ;
    	if(step==maxstep)
    	{
    		if(!diff())flag=1;
    		return ;
    	}
    	for(int i=0;i<8;i++)
    	{
    		int xx=x+nextx[i];
    		int yy=y+nexty[i];
    		if(check(xx,yy))continue;
    		swap(num[x][y],num[xx][yy]);
    		if(step+diff()<=maxstep)dfs(step+1,xx,yy,maxstep);
    		swap(num[x][y],num[xx][yy]);
    	}
    }
    int main()
    {
    	int t,stx,sty;
    	scanf("%d",&t);
    	while(t--)
    	{
    		flag=0;
    		for(int i=1;i<=5;i++)
    		{
    			scanf("%s",ch[i]+1);
    			for(int j=1;j<=5;j++)
    			{
    				if(ch[i][j]=='*')num[i][j]=2,stx=i,sty=j;	
    				else num[i][j]=ch[i][j]-'0';
    			}
    		}
    		for(int i=1;i<=15;i++)
    		{
    			dfs(0,stx,sty,i);
    			if(flag)
    			{
    				printf("%d
    ",i);
    				break;
    			}
    		}
    		if(!flag)puts("-1");
    	}	
    	return 0;
    }
    
  • 相关阅读:
    20151019
    20151013
    20150810
    20150626
    20150625
    20150530
    HTML特殊字符大全
    label标签跳出循环
    IIS 负载均衡
    .NET代码执行效率优化
  • 原文地址:https://www.cnblogs.com/ShuraEye/p/12110852.html
Copyright © 2011-2022 走看看