• [洛谷P2324][题解][SCOI2005]骑士精神


    题目戳我
    算是一个(IDA*)的经典题了吧

    0.(IDA*)介绍

    (A*):启发式搜索
    (IDS):迭代加深搜索
    我们来分别介绍。

    (A*)是什么

    (A*)是一种叫做启发式搜索的东西,它的主要思想是利用估价函数(h*)获得一个强力的剪枝
    设当前状态为(now),我们要求最少的搜索步数,那么令从(now)走到结束的步数为(h)
    显而易见,在真实情况下,我们是不能求出(h)的,于是我们就用(h*leq h)来代替

    (IDS)是什么

    在很多问题中,我们不能确定搜索的最大步数,这样如果爆搜的话就会获得RE or TLE
    于是我们就人为规定一个步数,超过了就返回(其实这里有点像BFS了),这种算法就叫做迭代加深搜索

    (IDA*)是什么

    迭代加深的时候加一个估价函数剪枝

    1.思路

    为什么这道题可以用(IDA*)呢?我们来关注两个点:
    (1)题目规定步数(leq 15),可以迭代加深
    (2)估价函数很容易求:假设每个棋子都可以随便跳,那么(h*)可以设为当前与最终状态不同的棋子数-1(-1是因为要除去空格)

    2.实现

    我们把空格当成一个棋子走,每走一步判断一下即可

    3.代码

    依然省去了缺省源

    const int dx[8]={2,1,-1,-2,-2,-1,1,2};
    const int dy[8]={1,2,2,1,-1,-2,-2,-1};
    const int ed[6][6]={ 
    {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}};
    int T,st[6][6],okay,sx,sy;
    inline int A_star(int now[6][6]){
    	int cnt=0;
    	for(rg int i=1;i<=5;i++){
    		for(rg int j=1;j<=5;j++){
    			if(now[i][j]!=ed[i][j])cnt++;
    		}
    	}
    	return cnt-1;//注意-1 
    }
    void DFS(int x,int y,int now[6][6],int limt,int cnt){
    	if(okay)return;
    	if(cnt+A_star(now)>limt)return;//A*剪枝 
    	if(A_star(now)==-1){
    		okay=1;
    		return;
    	}
    	for(rg int i=0;i<8;i++){//枚举空格可走的位置 
    		int xx=x+dx[i],yy=y+dy[i];
    		if(xx>=1&&xx<=5&&yy>=1&&yy<=5){
    			swap(now[x][y],now[xx][yy]);
    			DFS(xx,yy,now,limt,cnt+1);
    			swap(now[x][y],now[xx][yy]);
    		}
    	}
    }
    int main(){
    	Read(T);
    	while(T--){
    		okay=0;
    		for(rg int i=1;i<=5;i++){
    			char ipt[6];
    			cin>>ipt+1;
    			for(rg int j=1;j<=5;j++){
    				if(ipt[j]=='*'){
    					st[i][j]=2;
    					sx=i,sy=j;
    				}else st[i][j]=ipt[j]-'0';
    			}
    		}			
    		if(A_star(st)==-1){//已经是最终状态就不搜了 
    			cout<<0<<endl;
    			continue;
    		}
    		for(rg int i=1;i<=15;i++){//迭代加深,只枚举到15 
    			DFS(sx,sy,st,i,0);
    			if(okay){
    				cout<<i<<endl;
    				break;
    			}
    		}
    		if(!okay)cout<<-1<<endl;
    	}
    	return 0;
    }
    

    4.完结撒花

  • 相关阅读:
    linux下搭建lamp环境以及安装swoole扩展
    TP5 中引入第三方类库
    thinkphp5 查询的数据是对象时,获取原始数据方法
    thinkphp5 列表页数据分页查询3-带搜索条件
    thinkphp5 列表页数据分页查询2-带搜索条件
    thinkphp5 列表页数据分页查询-带搜索条件
    thinkphp5 怎么获取当前的模块,控制器和方法名
    限定页面执行时间,请求超时抛出异常或提示
    centos安装netcat
    redis在PHP中的基本使用案例
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12678287.html
Copyright © 2020-2023  润新知