• [模板A*][SCOI2005]骑士精神(A*,IDA*)


    在这里插入图片描述
    输入格式
    第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

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

    这题是一道比较好的(A*)的模板题,(A*)对dfs的优化一般叫(IDA*)

    首先,(A*)有一个定义式叫做:

    (f(n)=g(n)+h(n))

    (f(n))即为一点的估价函数,(g(n))是这一点实际所用的步数(价值),(h(n))是对未来的所需步数(代价)的完美预测(接近完美)。

    通过这个定义式,只要有h(n),每次都可以算出一个点的估价,(A*)算法就是通过限制估价,使得在搜索的时候不要在无意义的道路上浪费时间。即,每次限制每个点的估价(maxdep),一旦估价超过,就停止搜索。

    根据定义式,(h(n))一定要(<=)实际的所需步数。

    在这里插入图片描述
    像这张图,如果(h(A))估大了的话,(f(A))也会相应变大,这样(f(A))有可能会被maxdep给去掉,从而找不到正确答案。

    所以,为了保证答案的正确性,(h(A))一定要在(<=)实际的所需步数的前提下尽量的大,也就是尽量估得准。

    那回到这题,题目要求在15步以内完成才输出步数,否则-1,所以可以将maxdep从0到15枚举,一旦成功找到,那就是答案(最少步数)。

    而最优的就是每一次都将不在相应位置上的棋子移到相应的位置上,所以(h(A))可以是不匹配的棋子数,因为每次最多还原一个,所以(h(A))一定是(<=)实际的所需步数,正确性得到保证。

    (h(A))

    int value()
    {
    	int ans=0;
    	for(int i=0;i<5;i++)
    	{
    		for(int j=0;j<5;j++)
    		{
    			if(standard[i][j]!=tu[i][j])
    			{
    				ans++;
    			}
    		}
    	}
    	return ans;
    }
    

    然后就是时间的剪枝,题目要的是最少步数,所以肯定不能做回头路,还有就是没有找到完成的路径,满足这两点,加上maxdep的限制,才能继续往下搜。

    其他就是一个暴力搜索了,没什么好讲的:

    #include<bits/stdc++.h>
    using namespace std;
    int standard[5][5]={{1,1,1,1,1},{0,1,1,1,1},{0,0,-1,1,1},{0,0,0,0,1},{0,0,0,0,0}},tu[5][5],f[8][2]={{-2,-1},{-2,1},{1,2},{1,-2},{-1,2},{-1,-2},{2,-1},{2,1}},is,t,xx,yy;
    char ch;
    int value()//估价函数
    {
    	int ans=0;
    	for(int i=0;i<5;i++)
    	{
    		for(int j=0;j<5;j++)
    		{
    			if(standard[i][j]!=tu[i][j])
    			{
    				ans++;
    			}
    		}
    	}
    	return ans;
    }
    void dfs(int dep,int x,int y,int maxdep,int lastway)//直接搜
    {
    	if(dep==maxdep)
    	{
    		if(!value())
    		{
    			is=1;
    		}
    		return;
    	}
    	for(int i=0;i<8;i++)
    	{
    		int xx=x+f[i][0];
    		int yy=y+f[i][1];
    		if(xx<0||xx>4||yy<0||yy>4||7-i==lastway)//不走出格,不走回头路
    		{
    			continue;
    		}
    		swap(tu[x][y],tu[xx][yy]);
    		if(dep+value()<=maxdep&&!is)//估价函数的限制
    		{
    			dfs(dep+1,xx,yy,maxdep,i);
    		}
    		swap(tu[x][y],tu[xx][yy]);
    	}
    }
    int main()
    {
    	scanf("%d",&t);
    	while(t--)
    	{
    		is=0;
    		for(int i=0;i<5;i++)
    		{
    			for(int j=0;j<5;j++)
    			{
    				cin>>ch;
    				if(ch=='*')
    				{
    					tu[i][j]=-1;
    					xx=i;
    					yy=j;
    				}else{
    					tu[i][j]=ch-'0';
    				}
    			}
    		}
    		if(!value())
    		{
    			puts("0");
    			return 0;
    		}
    		for(int i=1;i<=15;i++)//A*
    		{
    			dfs(0,xx,yy,i,9);
    			if(is)
    			{
    				printf("%d
    ",i);
    				break;
    			}
    		}
    		if(!is)//没有
    		{
    			puts("-1");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Eclipse 修改maven 仓储Repository位置
    使用Eclipse构建Maven的SpringMVC项目
    The word is not correctly spelled问题解决
    navicat for mysql 显示中文乱码解决办法
    Missing artifact net.sf.json-lib:json-lib:jar:2.2.3:compile
    ApacheTiles实战
    使用Apache Tiles3.x构建界面布局
    SpringMVC整合Tiles框架
    最近遇到的问题
    Unity3D流行的游戏开发人员构建高速检查站系统
  • 原文地址:https://www.cnblogs.com/2017gdgzoi44/p/12111001.html
Copyright © 2020-2023  润新知