• LightOJ 1139 8 puzzle + hdu 1043 Eight A*


    这两道做时都是超时,无奈之下学习了一下A*算法,其实非常简单,就是加了一个获取当前状态到目的状态的长度(距离),很明显长度小的要排在前边,因此再加上优先队列

    就形成了一个完美的组合,......AC代码......,还有一个IDA*算法,还要继续学习一下………

    lightOJ 1139 8 puzzle

    A* + hash + 优先队列广度搜索

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <cstdio>
     5 using namespace std;
     6 
     7 int s, maze[9], c[] = { 112624120720504040320362880 };
     8 int visit[363000], parent[363000], d[363000],
     9 dir[4][2] = {{-1,0}, {1,0}, {0,-1}, {01}}; // u d l r
    10 
    11 
    12 struct node{
    13     int n[10]; //保存maze
    14     int key, x; //maze对就的hash值和x所在的位置
    15     int f, g;   //估价值和移动的步数
    16     bool operator < (const node& n) const{//当估价值相等时,步数小的先出队
    17         return f > n.f || (f == n.f && g > n.g);
    18     }
    19 };
    20 
    21 int cantor(int s[],int n){
    22     int i, temp, num = 0;
    23     for(i = 0; i < n; i++){
    24         temp = 0;
    25         for(int j = i + 1; j < n; j++)
    26             if (s[j] < s[i]) temp++;
    27         num += c[n-i-1] * temp;
    28     }
    29     return num;
    30 }
    31 int abs(int n) {return n > 0 ? n : (-n); }
    32 int get_h(int s[], int n){  //获取估价值,就是到目的状态的距离
    33     int sum = 0;
    34     for(int i = 0; i < n; ++i){
    35         if(s[i] == 9continue;
    36         sum += ( abs(i / 3 - (s[i] - 1) / 3) +  abs(i % 3 - (s[i]-1) % 3) );
    37     }
    38     return sum;
    39 }
    40 
    41 bool f(int s[], int n){  //求逆序数,如果为奇数,则不能到目的状态
    42     int i, j, t = 0;
    43     for(i = 0; i < n - 1; ++i){
    44         if(s[i] == 9continue;
    45         for(j = i+1; j < n; ++j)
    46             if(s[i] > s[j]) ++t;
    47     }
    48     if(t&1return true;
    49     return false;
    50 }
    51 
    52 void bfs(){ //优先队列+广搜
    53     node n1, n2; int i, x, y;
    54     memset(visit, falsesizeof(visit));
    55     for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor(n1.n, 9);
    56     n1.g = 0; n1.f = get_h(n1.n, 9);
    57     priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent[n1.key] = -1;
    58     if(n1.key == 0) {cout<<0<<endl; return;}
    59     while(!q.empty()){
    60         n1 = q.top(); q.pop();
    61         x = n1.x / 3; y = n1.x % 3;
    62         for(i = 0; i < 4; ++i){
    63             n2 = n1;
    64             int xx = x + dir[i][0], yy = y + dir[i][1];
    65             if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
    66                 n2.x = xx * 3 + yy;
    67                 swap(n2.n[n1.x], n2.n[n2.x]);
    68                 n2.key = cantor(n2.n, 9);
    69                 if(!visit[n2.key]){
    70                     n2.g++; n2.f = n2.g + get_h(n2.n, 9);
    71                     visit[n2.key] = true; d[n2.key] = i; parent[n2.key] = n1.key;
    72                     if(n2.key == 0) { cout<<n2.g<<endl; return; } q.push(n2);
    73                 }
    74             }
    75         }
    76     }
    77  //   cout<<"impossible"<<endl;
    78 }
    79 int main(){
    80     int t, i, cas; cin>>t;
    81     for(cas = 1; cas <= t; ++cas){
    82         cout<<"Case "<<cas<<"";
    83         for(i = 0; i < 9; ++i) {cin>>maze[i]; if(maze[i] == 0) { s = i; maze[i] = 9;} }
    84         if(f(maze, 9)) cout<<"impossible"<<endl;
    85         else bfs();
    86     }
    87     return 0;
    88 }
    View Code

     hdu 1043 Eight

    A* + hash + 优先队列广度搜索 + 记录路径 代码和上边的基本一致,只是稍微修改了一下
      1 #include <iostream>
      2 #include <cstring>
      3 #include <queue>
      4 #include <algorithm>
      5 #include <cstdio>
      6 using namespace std;
      7 
      8 int s, maze[9], c[] = { 112624120720504040320362880 };
      9 int visit[363000], parent[363000], d[363000],
     10 dir[4][2] = {-10100, -101}; // u d l r
     11 
     12 
     13 struct node{
     14     int n[10]; //保存maze
     15     int key, x; //maze对就的hash值和x所在的位置
     16     int f, g;   //估价值和移动的步数
     17     bool operator < (const node& n) const{
     18         return f > n.f || (f == n.f && g > n.g);
     19     }
     20 };
     21 
     22 int cantor(int s[],int n){  //康托展开,全排列,保存当前maze是哪个状态
     23     int i, temp, num = 0;
     24     for(i = 0; i < n; i++){
     25         temp = 0;
     26         for(int j = i + 1; j < n; j++)
     27             if (s[j] < s[i]) temp++;
     28         num += c[n-i-1] * temp;
     29     }
     30     return num;
     31 }
     32 int abs(int n) {return n > 0 ? n : (-n); }
     33 int get_h(int s[], int n){  //获取估价值,就是到目的状态的距离
     34     int sum = 0;
     35     for(int i = 0; i < n; ++i){
     36         if(s[i] == 9continue;
     37         sum += ( abs(i / 3 - (s[i] - 1) / 3) +  abs(i % 3 - (s[i]-1) % 
     38 
     39 3) );
     40     }
     41     return sum;
     42 }
     43 
     44 void print_path(){  //打印路径
     45     int i, t = 0string path;
     46     while(parent[t] != -1){
     47         if(d[t] == 0) path += 'u';
     48         else if(d[t] == 1) path += 'd';
     49         else if(d[t] == 2) path += 'l';
     50         else path += 'r';
     51         t = parent[t];
     52     }
     53     for(i = path.length() - 1; i >= 0; --i) putchar(path[i]);
     54 }
     55 
     56 bool f(int s[], int n){  //求逆序数,如果为奇数,则不能到目的状态
     57     int i, j, t = 0;
     58     for(i = 0; i < n - 1; ++i){
     59         if(s[i] == 9continue;
     60         for(j = i+1; j < n; ++j)
     61             if(s[i] > s[j]) ++t;
     62     }
     63     if(t&1return true;
     64     return false;
     65 }
     66 
     67 void bfs(){ //优先队列+广搜
     68     node n1, n2; int i, x, y;
     69     memset(visit, falsesizeof(visit));
     70     for(i = 0; i < 9; ++i) n1.n[i] = maze[i]; n1.x = s; n1.key = cantor
     71 
     72 (n1.n, 9);
     73     n1.g = 0; n1.f = get_h(n1.n, 9);
     74     priority_queue<node> q; q.push(n1); visit[n1.key] = true; parent
     75 
     76 [n1.key] = -1;
     77     if(n1.key == 0) {return;}
     78     while(!q.empty()){
     79         n1 = q.top(); q.pop();
     80         x = n1.x / 3; y = n1.x % 3;
     81         for(i = 0; i < 4; ++i){
     82             n2 = n1;
     83             int xx = x + dir[i][0], yy = y + dir[i][1];
     84             if(xx >= 0 && yy >= 0 && xx <= 2 && yy <= 2){
     85                 n2.x = xx * 3 + yy;
     86                 swap(n2.n[n1.x], n2.n[n2.x]);
     87                 n2.key = cantor(n2.n, 9);
     88                 if(!visit[n2.key]){
     89                     n2.g++; n2.f = n2.g + get_h(n2.n, 9);
     90                     visit[n2.key] = true; d[n2.key] = i; parent[n2.key] 
     91 
     92 = n1.key;
     93                     if(n2.key == 0) { print_path(); return; } q.push
     94 
     95 (n2);
     96                 }
     97             }
     98         }
     99     }
    100     printf("unsolvable");
    101 }
    102 
    103 int main(){
    104     char ss[100];
    105     while(gets(ss)){
    106         for(int i = 0, j = 0; ss[i]; ++i){
    107             if(ss[i] == ' 'continue;
    108             if(ss[i] == 'x') {maze[j++] = 9; s = j - 1;}
    109             else if(ss[i] >= '0' && ss[i] <= '9') maze[j++] = ss[i] - 
    110 
    111 '0';
    112         }
    113         if(f(maze, 9)) puts("unsolvable");
    114         else { bfs(); puts(""); }
    115     }
    116     return 0;
    117 }
    View Code
  • 相关阅读:
    查詢一個表中的所有字段,一个表的结构
    二月份工作總結
    导出excel [原创]
    一个it老总对于新人的一点建议
    命名空间的别名
    mssql 格式化时间 [转]
    开发人员一定要加入收藏夹的网站
    sql 导出/入Excel
    hibernate中hbm文件中inverse功能
    详细展示Asp.net页面的生命周期[转]
  • 原文地址:https://www.cnblogs.com/yaling/p/3242610.html
Copyright © 2020-2023  润新知