zoukankan      html  css  js  c++  java
  • IDA*算法

    http://poj.org/problem?id=1077
    
    
    /*
    procedure dfs(depth:longint);
     begin
      if 要剪枝 then exit;
      if 可行 then Print;
      if Depth<MaxDepth then dfs(depth+1);
     end;
    
    procedure Iterative_Deepening;
     begin
      MaxDepth:=0;
      while true do
       begin
        inc(MaxDepth);
        dfs(1);
       end;
     end;
    */
    
    #include <iostream> 
    #include <math.h> 
    using namespace std; 
    struct Status 
    { 
    	int board[3][3]; 
    	int px,py; 
    }; 
    Status init,target={1,2,3,4,5,6,7,8,9,2,2}; 
    int targetPos[10][2],path[10000],maxDepth; 
    int move[4][2]={0,-1,-1,0,0,1,1,0}; 
    
    /*
    *奇偶剪枝
    *每移动一次X方块,必定需要移动一次另外的方块
    *所以其他方块需要移动的次数+X方块移动的次数必定是偶数
    */
    bool IsSolvable() 
    { 
    	int i,j,k=0,sum=0,array[9]; 
    	for(i=0; i!=3; ++i) 
    		for(j=0; j!=3; ++j) 
    			array[k++] = init.board[i][j]; 
    	//除了X结点外,要到达目标位置需要移动的最大步数,因为在转换成了一维后原本可以上下移动的都被转化成了水平移动.
    	//但是幸运的是,他们是同奇同偶的.具体的证明我也不知道,画图有这么个规律
    	for(i = 0; i != 8; ++i) 
    		for(j = i + 1; j != 9; ++j) 
    			if(array[i] > array[j]) 
    				sum++; 
    	//这个是X方块到目标位置的最短步数,不管怎么移动,只要最后是在目标位置,必定是同奇同偶的.(简单的考虑就是撤销)
    	//而每一次的其他方块的移动都是与X方块的交换来实现的,所以他们的和必定是偶数
    	sum += abs(init.px - targetPos[9][0]) + abs(init.py - targetPos[9][1]); 	
    	return sum % 2 == 0; 
    }
    
    // heuristic function 
    //计算该状态需要移动的距离
    int H(Status &s)         
    { 
    	int sum=0, tmp; 
    	for(int i = 0; i != 3; ++i) 
    		for(int j = 0; j != 3; ++j) 
    		{ 
    			tmp = s.board[i][j]; 
    			if(tmp < 9) 
    				sum += abs(i - targetPos[tmp][0]) + abs(j-targetPos[tmp][1]); 
    		} 
    	return sum; 
    } 
    
    void Output(int depth) 
    {
    	for(int i=0; i < depth; ++i) 
    		if(path[i] == 0) 
    			cout<<'l'; 
    		else if(path[i] == 1) 
    			cout<<'u'; 
    		else if(path[i] == 2) 
    			cout<<'r'; 
    		else cout<<'d'; 
    } 
    
    bool IDAStar(Status &s, int depth, int h, int prev) 
    { 
    	if(memcmp(&s, &target, sizeof(Status)) == 0) 
    	{
    		Output(depth); 
    		return true; 
    	} 
    	if(depth >= maxDepth) 
    		return false; 
    	Status ns; int nh,nx,ny,tmp;  //next status 
    	for(int k = 0; k != 4; ++k) 
    	{ 
    		//这里会撤销上一步的移动,跳过
    		if(abs(k - prev) == 2) 
    			continue; 
    		ns = s; 
    		nx = s.px + move[k][0]; 
    		ny = s.py + move[k][1]; 
    		//越界
    		if(nx < 0 || ny < 0 || nx == 3 || ny == 3) 
    			continue; 
    		//移动操作
    		tmp = s.board[nx][ny]; 
    		ns.board[s.px][s.py] = tmp; 
    		ns.board[nx][ny] = 9; 
    		ns.px = nx; ns.py = ny; 
    		//向上移动,并且x在与他交换的方块的目标位置的上方,也就是说,与他交换的方块理目标位置近了一步
    		//可能在上方也可能就是那个位置了
    		if(k == 0 && ny < targetPos[tmp][1]) 
    			nh = h - 1;   // l 
    		else if(k == 1 && nx < targetPos[tmp][0]) 
    			nh = h - 1;  // u 
    		else if(k == 2 && ny > targetPos[tmp][1]) 
    			nh = h - 1;  // r 
    		else if(k == 3 && ny < targetPos[tmp][0]) 
    			nh = h - 1;  // d 
    		else 
    			nh = h + 1; //走歪路了.
    		//不是合法结点.h(n) + g(n) > f(n)..
    		if(depth + nh >= maxDepth) 
    			continue; 
    		path[depth] = k; 
    		if(IDAStar(ns, depth+1, nh, k)) 
    			return true; 
    	} 
    	return false; 
    }
    
    int main() 
    { 
    	char tmp; int index=0; 
    	for(int i = 0; i != 3; ++i) 
    		for(int j = 0; j != 3; ++j) 
    		{ 
    			cin>>tmp; 
    			if(tmp == 'x') 
    			{ 
    				tmp = '9'; 
    				init.px = i; 
    				init.py = j; 
    			} 
    			init.board[i][j] = tmp - '0'; 
    			targetPos[++index][0] = i; 
    			targetPos[index][1] = j; 
    		} 
    	if(IsSolvable()) 
    	{ 
    		int h = H(init); 
    		//迭代加深,搜索深度作为限制,这个算法还不是很了解..迭代加深..
    		for(maxDepth = h; ; maxDepth++) 
    			if(IDAStar(init, 0, h, -10)) 
    				break;         
    	} 
    	else 
    		cout<<"unsolvable"; 
    	return 0; 
    } 
    
    
    
  • 相关阅读:
    在 kylin-v10环境中搭建 electron
    二叉树建树
    python 从txt文件中提取数据保存到 xlxs 文件中
    openpyxl 插件写入数据
    python时间格式转换
    vue-typescript-element-template使用总结
    vue3入门
    typescript入门
    记录下谷歌 浏览器请求数据时遇302,重新连接的问题
    uni使用render.js视图层与逻辑层传数据 的问题
  • 原文地址:https://www.cnblogs.com/steady/p/1936551.html
Copyright © 2011-2022 走看看