码迷,mamicode.com
首页 > 其他好文 > 详细

广搜——最优方案

时间:2015-09-27 13:42:13      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

Wikioi 1225 八数码难题

 

题目描述 Description

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

 

输入描述 Input Description

输入初试状态,一行九个数字,空格用0表示

 

输出描述 Output Description

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

 

样例输入 Sample Input

283104765

 

样例输出 Sample Output

4

 

数据范围及提示 Data Size & Hint

详见试题

思路:

(康托展开+双向广搜) or ida*

代码:

①双向广搜:

技术分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 #include<algorithm>
  9 #define mx 4000000
 10 using namespace std;
 11 
 12 struct chess{
 13     int node[9];
 14     int step;
 15     int pos;
 16     bool cla;
 17 };
 18 int chart = 0,step[2][10000];
 19 map<int,int> trans[2];
 20 chess start,end;
 21 bool jud[2][mx];
 22 int m_jud[9][4] = {1,3,-1,-1,
 23                    0,4,2,-1,
 24                    1,5,-1,-1,
 25                    0,4,6,-1,
 26                    1,3,5,7,
 27                    2,4,8,-1,
 28                    3,7,-1,-1,
 29                    4,6,8,-1,
 30                    5,7,-1,-1};
 31 
 32 int getval(chess x){
 33     int res = 1,val = 0;
 34     for(int i = 1;i <= 9;i++){
 35         val += res * x.node[i-1];
 36         res *= (i+1);
 37     }
 38     return val;
 39 }
 40 void putout(chess pt){
 41     cout<<"the class:"<<pt.cla<<endl;
 42     for(int i = 1;i <= 3;i++){
 43         for(int j = 1;j <= 3;j++){
 44             cout<<pt.node[(i-1) * 3 + j - 1] <<" ";
 45         }
 46         cout<<endl;
 47     }
 48     cout<<"steps: "<<pt.step<<" , pos: "<<pt.pos<<endl;
 49 }
 50 void init(){
 51     int co,md = 1;
 52     cin>>co;
 53     for(int i = 8;i >= 0;i--){
 54         start.node[i] = (co / md)% 10;
 55         md *= 10;
 56         if(start.node[i] == 0) start.pos = i;
 57         
 58     }
 59     start.cla = 0;
 60     end.node[0] = 1;
 61     end.node[1] = 2;
 62     end.node[2] = 3;
 63     end.node[3] = 8;
 64     end.node[4] = 0;
 65     end.node[5] = 4;
 66     end.node[6] = 7;
 67     end.node[7] = 6;
 68     end.node[8] = 5;
 69     end.step = start.step = 0;
 70     end.pos = 4;
 71     end.cla = 1;
 72 }
 73 void bfs(){
 74     queue<chess> now,then;
 75     now.push(start);
 76     now.push(end);
 77     chess test,h;
 78     int p,code;
 79     while(!now.empty()){
 80         h = now.front();
 81         p = h.pos;
 82         code = getval(h);
 83         trans[h.cla][code] = chart;
 84         step[h.cla][chart] = h.step;
 85         chart++;
 86         jud[h.cla][code] = 1;
 87         for(int i = 0,j = m_jud[p][i];j != -1 && i <= 3;i++,j = m_jud[p][i]){
 88             test = h;
 89             test.step++;
 90             swap(test.node[p],test.node[j]);
 91             code = getval(test);
 92             //if(jud[test.cla][code]) continue;
 93             test.pos = j;
 94             trans[test.cla][code] = chart;
 95             step[test.cla][chart] = test.step;
 96             chart++;
 97             if(jud[!test.cla][code]){
 98                 cout<<step[0][trans[0][code]] + step[1][trans[1][code]]<<endl;
 99                 return;
100             }
101             if(!jud[test.cla][code]){
102                 now.push(test);
103                 jud[test.cla][code] = 1;
104             }
105             
106         }
107         now.pop();
108     }
109 }
110 int main(){
111 
112     init();    
113     bfs();
114     return 0;
115 }
View Code

②IDA*:

技术分享
  1 #include <iostream>
  2 #include <cmath>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cstring>
  6 using namespace std;
  7 const unsigned int M = 1001;
  8 int dir[4][2] = {
  9     1, 0, // Down
 10     -1, 0, // Up
 11     0,-1, // Left
 12     0, 1 // Right
 13 };
 14 typedef struct STATUS{
 15     int arr[3][3];
 16     int r,c;
 17 }STATUS;
 18 char dirCode[] = {"dulr"};
 19 char rDirCode[] = {"udrl"};
 20 char path[M]; // 最优解
 21 STATUS begin, end = { 1,2,3,4,5,6,7,8,0,2,2 }; // 起始和终止状态
 22 int maxDepth = 0; // 深度边界
 23 int diff(const STATUS &cur) // 启发函数
 24 {
 25     int i,j,k,m,ans=0;
 26     for(i=0;i<=2;i++)
 27         for(j=0;j<=2;j++)
 28         {
 29             if(cur.arr[i][j] != 0)
 30             {
 31                 for(k=0;k<=2;k++)
 32                     for(m=0;m<=2;m++)
 33                     {
 34                         if(cur.arr[i][j] == end.arr[k][m])
 35                         {
 36                             ans+=abs(i-k)+abs(j-m);
 37                             break;
 38                         }
 39                     }
 40             }
 41         }
 42     return ans;
 43 }
 44 bool dfs(STATUS &cur, int depth, int h, char preDir)
 45 {
 46     if(memcmp(&cur, &end, sizeof(STATUS)) == 0 )
 47     { // OK找到解了:)
 48         path[depth] = /0;
 49         return true;
 50     }
 51     if( depth + h > maxDepth ) return false; // 剪枝
 52     STATUS nxt; // 下一状态
 53     for(int i=0; i<4; i++)
 54     {
 55         if(dirCode[i]==preDir) continue; // 回到上次状态,剪枝
 56         nxt = cur;
 57         nxt.r = cur.r + dir[i][0];
 58         nxt.c = cur.c + dir[i][1];
 59         if( !( nxt.r >= 0 && nxt.r < 3 && nxt.c >= 0 && nxt.c < 3 ) )
 60             continue;
 61         int nxth = h;
 62         int preLen,Len,desNum=cur.arr[nxt.r][nxt.c],desR=(desNum-1)/3,desC=(desNum-1)%3;
 63         preLen=abs(nxt.r-desR)+abs(nxt.c-desC);
 64         Len=abs(cur.r-desR)+abs(cur.c-desC);
 65         nxth = h - preLen + Len;
 66         swap(nxt.arr[cur.r][cur.c], nxt.arr[nxt.r][nxt.c]);
 67         path[depth] = dirCode[i];
 68         if(dfs(nxt, depth + 1, nxth, rDirCode[i]))
 69             return true;
 70     }
 71     return false;
 72 }
 73 int IDAstar()
 74 {
 75     int nh = diff(begin);
 76     maxDepth = nh;
 77     while (!dfs(begin, 0, nh, /0))
 78         maxDepth++;
 79     return maxDepth;
 80 }
 81 void Input()
 82 {
 83     char ch;
 84     int i, j;
 85     for(i=0; i < 3; i++){
 86         for(j=0; j < 3; j++){
 87             do{
 88                 scanf("%c", &ch);
 89             }
 90             while( !( ( ch >= 1 && ch <= 8 ) || ( ch == x ) ) ) 
 91                 ;
 92             if( ch == x ) {
 93                 begin.arr[i][j] = 0;
 94                 begin.r = i;
 95                 begin.c = j;
 96             }
 97             else
 98                 begin.arr[i][j] = ch - 0;
 99         }
100     }
101 }
102 bool IsSolvable(const STATUS &cur)
103 {
104     int i, j, k=0, s = 0;
105     int a[8];
106     for(i=0; i < 3; i++){
107         for(j=0; j < 3; j++){
108             if(cur.arr[i][j]==0) continue;
109             a[k++] = cur.arr[i][j];
110         }
111     }
112     for(i=0; i < 8; i++){
113         for(j=i+1; j < 8; j++){
114             if(a[j] < a[i])
115                 s++;
116         }
117     }
118     return (s%2 == 0);
119 }
120 int main()
121 {
122     Input();
123     if(IsSolvable(begin)){
124         IDAstar();
125         printf("%s/n", path);
126     }
127     else
128         printf("unsolvable/n");
129     return 0;
130 }
View Code

 

广搜——最优方案

标签:

原文地址:http://www.cnblogs.com/hyfer/p/4842112.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!