hdu1813 IDA*算法

本文介绍如何使用IDA*算法解决一个特定的棋盘问题,即从任意非边缘的有效位置出发,找到能够到达棋盘边缘的最短指令序列。文章详细解释了IDA*算法的实现过程,并给出了具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题的题意是:从棋子上的任意一点(边缘、坏的棋子除外),都能按照某一指令走到边缘,求这个最短的指令。

 

一开始看到这个题的时候一点思路也没有,后来看了一下别人的解题报告,才明白用的是IDA*算法,IDA*算法就是A*算法+迭代。

解题思路为:

1.用BFS求出棋子上所有点到边缘的距离

2.用A*算法进行预先判断,A*算法是预先判断的算法,不同于dfs和bfs这种盲目搜索算法,他可以大大的减少时间的复杂度,如果当前节点的深度+当前状态下棋子上任意一节点到边缘的最大值>确定的最大深度,则return false。

3.运用迭代一次加深进行搜索,最大深度从1开始搜索,一直到找到为止。

 

代码参考的论坛上某一大神的代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

#define inf 1<<30;
typedef pair<int,int>PP;


struct Node{
	int x,y;
}node[44];

char str[11][11];
int map[11][11],Index[1111],dist[11][11];
int n,m,maxdeep;
int dir[4][2]={{0,1},{-1,0},{1,0},{0,-1}};

bool In_Edge(int x,int y){
	if(x==1||x==n||y==1||y==n)
	return true;
	return false;
}

//bfs用来求到边缘的最短长度 
int bfs(int x,int y){
	queue<PP>que;
	que.push(make_pair(x,y));
	int dd[11][11];
	memset(dd,-1,sizeof(dd));
	dd[x][y]=0;
	while(!que.empty()){
		x=que.front().first,y=que.front().second;
		que.pop();
		if(In_Edge(x,y))
		return dd[x][y];
		
		for(int i=0;i<4;i++){
			int xx=x+dir[i][0],yy=y+dir[i][1];
			if(map[xx][yy]&&dd[xx][yy]==-1){
				dd[xx][yy]=dd[x][y]+1;
				que.push(make_pair(xx,yy));
			}
		}
	}
	return -1;
}

int Get_H(Node node[]){
	int max_dist=0;
	for(int i=0;i<m;i++){
		max_dist=max(max_dist,dist[node[i].x][node[i].y]);
	}
	return max_dist;
}


bool IDA_star(int deep,Node node[]){
	//A*剪枝 
	if(Get_H(node)+deep>maxdeep)
	return false;
	
	if(deep==maxdeep)
	return true;
	
	Node tmp_node[44];
	for(int i=0;i<4;i++){
		Index[deep]=i;
		
		for(int j=0;j<m;j++){
			int xx=node[j].x+dir[i][0],yy=node[j].y+dir[i][1];
			//如果这个方向不能继续往下走 
			if(In_Edge(node[j].x,node[j].y)||map[xx][yy]==0){
				tmp_node[j]=node[j];
			}
			//这个方向能继续走 
			else
			tmp_node[j].x=xx,tmp_node[j].y=yy;
		}
		if(IDA_star(deep+1,tmp_node))
		return true;
	}
	return false; 
	
}


int main(){
	int t=0;
	
	while(scanf("%d",&n)!=EOF){
		if(t++){
			puts("");
		}
		
		for(int i=1;i<=n;i++){
			scanf("%s",str[i]+1);
			for(int j=1;j<=n;j++)
			map[i][j]=1-(str[i][j]-'0');
		}
		
		
		m=0;
	
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(map[i][j]){
					if(In_Edge(i,j))
					dist[i][j]=0;
					else{
						dist[i][j]=bfs(i,j);
						node[m].x=i,node[m++].y=j;
					}
				}
				else{
					dist[i][j]=inf;
				}
				
			}
		}
	    
		if(m==0)
		continue;
		for(maxdeep=1;;maxdeep++){
			if(IDA_star(0,node))
			break;
		}
		
		for(int i=0;i<maxdeep;i++){
			if(Index[i]==0)
			puts("east");
			else if(Index[i]==1)
			puts("north");
			else if(Index[i]==2)
			puts("south");
			else if(Index[i]==3)
			puts("west");
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值