Chinaunix首页 | 论坛 | 博客
  • 博客访问: 738396
  • 博文数量: 251
  • 博客积分: 10367
  • 博客等级: 上将
  • 技术积分: 2750
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-10 14:43
文章分类

全部博文(251)

文章存档

2009年(2)

2008年(86)

2007年(163)

分类: C/C++

2008-03-19 16:48:14

采用A*算法

另处,8数码问题也可能没解:
/*
将一个八数码的状态对应到一个序列,例如:
1 2 3 
4 5 6 
8 7 
可对应于序列:1 2 3 4 5 6 8 7 

对于空格的左移/右移操作,对应序列不变(逆序数也就不变)
对于空格的上移/下移操作,相当于序列的某个数字前移/后移两位,该序列的逆序数奇偶性不变。

综上所述,两个互相可达的状态对应序列逆序数的奇偶性应该相同

1 2 3 4 5 6 8 7奇偶性为1
1 2 3 4 5 6 7 8奇偶性为0
所以两状态相互不可达

摘自:
*/

测试:

[heixia@localhost program]$ ./test<t8
   1 2 3
   4 5 6
   8 7

   1 2 3
   4 5
   8 7 6

   1 2 3
   4 5
   8 7 6

   1 2 3
       4 5
   8 7 6

   1 2 3
   8 4 5
       7 6

   1 2 3
   8 4 5
   7 6

   1 2 3
   8 4 5
   7 6

   1 2 3
   8 4
   7 6 5

   1 2 3
   8 4
   7 6 5


t8文件:
1 2 3 4 5 6 8 7 -1
1 2 3 8 -1 4 7 6 5

[heixia@localhost program]$ ./test<t8
Sorry,I have done what I can do.


t8文件:

1 2 3 4 5 6 7 8 -1
1 2 3 8 -1 4 7 6 5



/* -*- C -*-
 *
 * 8_number.c - 8数码码问题,采用A*算法,调试了5个小时左右,相当的痛苦!还是要多编程才行啊!又见指针忽悠我!
 *
 * Author : heixia
 * Created On : Tue Mar 18 10:04:05 2008
 *
 */


#include <stdio.h>
#include <stdlib.h>

#define N 3
#define MAX 5000 //寻找的最大步数,有些可能找不到结果


typedef struct num * Num;
struct num{
     int depth;
     int cost;
     int direction; //0:up,1:down,2:left,3:right.

     int i,j; //indicate the position of the blank.

     int a[ N ][ N ];
     Num pre;
     Num father;
};

Num goal;

int n = 0;

int search(Num start);
int check( Num now,Num tobe );
void Print( Num to );
Num creatNum( Num now,int direction );
Num update( Num toupdate,Num new_num );

//main

int main( ){
     int i,j;
     Num start;
     
     start = ( Num )malloc( sizeof( *start ) );
     goal = ( Num )malloc( sizeof( *goal ) );

     if( start == NULL || goal == NULL ){
          printf( "Memory overflow.\n" );
          return 0;
     }

     start->depth = 0;
     start->direction = -1;
     start->pre = NULL;
     start->father = NULL;
     
// printf( "please input the inital state:\n" );


     for(i = 0;i < N; i ++ )
          for( j = 0; j < N; j ++ ){
              scanf( "%d",&start->a[ i ][ j ] );
              if( start->a[ i ][ j ] == -1 ){
                  start->i = i;
                  start->j = j;
              }
           }

     // printf( "\nNow you can input the goal:\n" );


     for(i = 0;i < N; i ++ )
          for( j = 0; j < N; j ++ ){
              scanf( "%d",&goal->a[ i ][ j ] );
          }

     search( start );
     
     return 0;
}

int search(Num start){
     Num current = NULL;
     Num toVisit = start,new_num;
     int i;
     int step = 0;

     while( toVisit ){
          step ++;
          if( step > MAX ){
               printf( "Sorry,I have done what I can do.\n");
               break;
          }
          current = toVisit;
          // pr( current );

          toVisit = toVisit->pre;
          // pop( toVisit );

          if( check( current,goal ) ){
              Print( current );
              return 0;
          }
          else {
              for( i = 0; i < 4; i ++ ){
                   if( current->direction != i ){
                         new_num = creatNum( current,i );
                         if( new_num != NULL ){
                              // pr( new_num );

                              toVisit = update( toVisit,new_num );
        
                              // Print( toVisit );

                         }
                   }
               }
          }
     }

     //释放内存

     current = toVisit;
     
     while( current ){
          toVisit = toVisit->pre;
          free( current );
          current = toVisit;
     }
}
/*This is wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void pop( Num toVisit ){
     toVisit = toVisit->pre;
     }*/



int check( Num now,Num tobe ){

     // ==> 08.11.8 change
     // int **b,**c;

     // ==>

     int (*b)[N],(*c)[N];

     // <==
     int i,j;
     
     b = now->a;
     c = tobe->a;

     for( i = 0; i < N ;i ++ )
          for( j = 0; j < N ; j ++ ){
               if( now->a[ i ][ j ] != tobe->a[ i ][ j ])
                    return 0;
          }

     return 1;
}

void Print( Num to ){
     int i,j;
     
     if( to->father != NULL ){
          Print( to->father );
     }

     for( i = 0; i < N; i ++ ){
          for( j = 0; j < N ; j ++ ){
               if( to->a[ i ][ j ] != -1)
                    printf( "%4d" ,to->a[ i ][ j ]);
               else
                    printf( " " );
          }
          printf( "\n" );
     }
     printf( "\n" );
}

/* just for debug
void pr( Num to ){
     int i,j;

     for( i = 0; i < N; i ++ ){
          for( j = 0; j < N ; j ++ ){
               if( to->a[ i ][ j ] != -1)
                    printf( "%4d" ,to->a[ i ][ j ]);
               else
                    printf( " " );
          }
          printf( "\n" );
     }
     printf( "\n" );
}
*/


Num creatNum( Num now,int direction ){
     Num new_num;
     int i,i_old,j,j_old,h,k,cost = 0;
     int n1 = 0,n2 = 0;
     
     i = i_old = now->i;
     j = j_old = now->j;
     

     new_num = ( Num )malloc( sizeof( *new_num ) );
     
     switch( direction ){
     case 0:i--; new_num->direction = 1; break;
     case 1:i++; new_num->direction = 0; break;
     case 2:j--; new_num->direction = 3; break;
     case 3:j++; new_num->direction = 2; break;
     default: printf( "error direction.\n" ); return NULL;
     }

     if( i < 0 || i >= N || j < 0 || j >= N ){
          free( new_num );
          return NULL;
     }

     for( h = 0; h < N; h ++ )
          for( k = 0 ; k < N ;k ++ ){
               new_num->a[ h ][ k ] = now->a[ h ][ k ];
          }

     new_num->a[ i_old ][ j_old ] = now->a[ i ][ j ];
     new_num->a[ i ][ j ] = -1;

     new_num->depth = now->depth + 1;

     new_num->i = i;
     new_num->j = j;
/*
     for( h = 0; h < N; h ++ )
          for( k = 0 ; k < N ;k ++ ){
               if( new_num->a[ h ][ k ] != goal->a[ h ][ k ])
                    new_num->cost ++;
          }
*/

     if( now->a[ i_old ][ j_old ] != goal->a[ i_old ][ j_old ] )
          n1++;
     if( now->a[ i ][ j ] != goal->a[ i ][ j ] )
          n1++;
     
     if( new_num->a[ i_old ][ j_old ] != goal->a[ i_old ][ j_old ] )
          n2++;
     if( new_num->a[ i ][ j ] != goal->a[ i ][ j ] )
          n2++;

     new_num->cost = now->cost + ( n2 - n1 ) + 1; //+1 is because new_num->depth = now->depth + 1;

     new_num->pre = NULL;
     new_num->father = now;
      
     return new_num;
}

Num update( Num toupdate,Num new_num ){
     Num temp,p;

// temp = ( Num )malloc( sizeof( *temp ) ); 不需要!

// p = ( Num )malloc( sizeof( *p ) );

     p = temp = toupdate;

     if( toupdate != NULL ){
          while( temp != NULL && temp->cost < new_num->cost ){
             p = temp;
             temp = temp->pre;
          }
          if( toupdate->cost >= new_num->cost ){
              new_num->pre = toupdate;
              toupdate = new_num;
          }
          else {
              p->pre = new_num;
              new_num->pre = temp;
          }
     }
     else{
          toupdate = new_num;
     }
     
     return toupdate;
}

阅读(1569) | 评论(4) | 转发(0) |
0

上一篇:自动机

下一篇:KMP

给主人留下些什么吧!~~

chinaunix网友2008-11-08 09:58:10

哥们 你那个变成是用 c语言写的? 还是用 C++?用c 为什么 加//的注释? 我拿 TURBOC2 和 c++ builder都试呢都右错误 int **b,**c; int i,j; b = now->a; c = tobe->a; 提示有错误

chinaunix网友2008-11-01 23:54:07

呵,不好表述

chinaunix网友2008-10-24 17:40:46

补充说明一下 你怎么证明你的h函数也就是你的 cost小于实际的h*???? 无法证明的话你的算法就只能叫A算法,不能叫A*

chinaunix网友2008-10-24 17:39:38

很好很强大 A*搜索中的战斗机 fx已用,请CSA的其他同学让路哦! - -