⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 八数码问题程序.txt

📁 实现八数码问题
💻 TXT
字号:
// wangdan_qifashi.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <map>
#include <memory.h>
using namespace std;
#define SIZE 1000000

struct QUEUE{                                           //用顺序结构定义一个最小二叉堆
 int data,pre,f,deep;
}heap[SIZE];                                               

int pout,tail,ter[3][3] = {{1,2,3},{8,0,4},{7,6,5}},sta[9];

struct OUT{
 int data,pre;
}out[SIZE];

void swap(QUEUE &a, QUEUE &b)                           //结构体交换值
{
 int temp = a.data; a.data = b.data; b.data = temp;
 temp = a.pre; a.pre = b.pre; b.pre = temp;
 temp = a.f; a.f = b.f; b.f = temp;
 temp = a.deep; a.deep = b.deep; b.deep = temp;
}

QUEUE pop()                                            //进堆
{
 int p,t;
 swap(heap[1],heap[tail]);
 tail--;
 p = 1;
 while((t = 2*p) <= tail){
  if(t+1 <= tail && heap[t].f > heap[t+1].f)
   t++;
  if(heap[p].f > heap[t].f){
   swap(heap[p],heap[t]);
   p = t;
  }
  else
   break;
 }
 return heap[tail+1];
}

void push(QUEUE a)                                        //出堆
{ 
 int p,t;
 tail++;
 heap[tail].data = a.data;
 heap[tail].f = a.f;
 heap[tail].pre = a.pre;
 heap[tail].deep = a.deep;
 p = tail;
 while((t = p/2) >= 1){
  if(heap[t].f > heap[p].f)
   swap(heap[t],heap[p]);
  else
   break;
 }
}

int nxnum(int p[9])                            //求逆序对
{
 int i,j,re = 0;
 for(i = 0; i < 8; i++){
  if(p[i] == 0)
   continue;
  for(j = i+1; j < 9; j++){
   if(p[j] == 0)
    continue;
   if(p[i] > p[j])
    re++;
  }
 }
 return re;
}

int H(int p[3][3])                            //估价函数h
{
 int i,j,re = 0;
 for(i = 0; i < 3; i++){
  for(j = 0; j < 3; j++){
   if(p[i][j] != ter[i][j])
    re++;
  }
 }
 return re;
}

bool astar(int s)                              // 启发式搜索
{
 map<int,int>mp;
 tail = 1;
 heap[1].data = s;
 heap[1].pre = -1;
 heap[1].deep = 0;
 out[0].data = s;
 out[0].pre = -1;
 pout = 0;
 QUEUE tstatu,add;
 int temp[3][3],i,j,tf,x,y,tt[3][3];
 while(tail >= 1){
  tstatu = pop();
  out[++pout].data = tf = tstatu.data;
  out[pout].pre = tstatu.pre;
  for(i = 2; i >= 0; i--){
   for(j = 2; j >= 0; j--){
    temp[i][j] = tf%10;
    if(temp[i][j] == 0){
     x = i; 
     y = j;
    }
    tf /= 10;
   }
  }
  if(x > 0){                  // 上移
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tt[i][j] = temp[i][j];
    }
   }
   tf = tt[x][y];
   tt[x][y] = tt[x-1][y];
   tt[x-1][y] = tf;
   tf = 0;
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tf = tf*10 + tt[i][j];
    }
   }
   if(mp[tf] == 0){
    mp[tf] = 1;
    add.data = tf;
    add.deep = tstatu.deep+1;
    i = H(tt);
    add.f = add.deep + i;
    add.pre = pout;
    if(i == 0)
     return true;
    push(add);
   }
  }
  if(y > 0){                            //左移
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tt[i][j] = temp[i][j];
    }
   }
   tf = tt[x][y];
   tt[x][y] = tt[x][y-1];
   tt[x][y-1] = tf;
   tf = 0;
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tf = tf*10 + tt[i][j];
    }
   }
   if(mp[tf] == 0){
    mp[tf] = 1;
    add.data = tf;
    add.deep = tstatu.deep+1;
    i = H(tt);
    add.f = add.deep + i;
    add.pre = pout;
    if(i == 0)
     return true;
    push(add);
   }
  }
  if(x < 2){                                 //下移
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tt[i][j] = temp[i][j];
    }
   }
   tf = tt[x][y];
   tt[x][y] = tt[x+1][y];
   tt[x+1][y] = tf;
   tf = 0;
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tf = tf*10 + tt[i][j];
    }
   }
   if(mp[tf] == 0){
    mp[tf] = 1;
    add.data = tf;
    add.deep = tstatu.deep+1;
    i = H(tt);
    add.f = add.deep + i;
    add.pre = pout;
    if(i == 0)
     return true;
    push(add);
   }
  }
  if(y < 2){                           //右移
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tt[i][j] = temp[i][j];
    }
   }
   tf = tt[x][y];
   tt[x][y] = tt[x][y+1];
   tt[x][y+1] = tf;
   tf = 0;
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     tf = tf*10 + tt[i][j];
    }
   }
   if(mp[tf] == 0){
    mp[tf] = 1;
    add.data = tf;
    add.deep = tstatu.deep;
    i = H(tt);
    add.f = add.deep + i;
    add.pre = pout;
    if(i == 0)
     return true;
    push(add);
   }
  }
 }
 return false;
}

int no = 1,ot[3][3];

void print(int k)                                  // 打印结果
{
 if(out[k].pre != -1){
  print(out[k].pre);
  int i,j,f = out[k].data,tt;
  printf("第%d步:\n",no++);
  for(i = 2; i >= 0; i--){
   for(j = 2; j >=  0; j--){
    ot[i][j] = f%10;
    f /= 10;
   }
  }
  for(i = 0; i < 3; i++){
   for(j = 0; j < 3; j++){
    if(ot[i][j] == 0)
     printf("  ");
    else
     printf("%d ",ot[i][j]);    
   }
   printf("\n");
  }
  printf("\n");
 }
}

int main()                                                //主函数
{
 int i,j,k,temp[9],s;
 bool used[9] = {0};
 char op[10];
 printf("----------------------\n");
 printf("|             八数码问题求解程序:            |\n");
 printf("| 遥感院S071班      王丹      200722130012    |\n");
 printf("|         本程序采用的是启发式搜索方法        |\n");
 printf("----------------------\n\n\n");
 printf("本程序默认目标状态为:\n");
 for(i = 0; i < 3; i++){
  for(j = 0; j < 3; j++){
   printf("%d ",ter[i][j]);
  }
  printf("\n");
 }
 while(1){
  printf("是否想自定义目标状态?是请输入y,否请输入n:");
  scanf("%s",op);
  if(op[0] == 'y'){
   printf("请参照上面的样式输入目标状态(空白位置以0代替):\n");
   for(i = 0; i < 3; i++){
    for(j = 0; j < 3; j++){
     scanf("%d",&ter[i][j]);
    }
   }
  }
  else if(op[0] != 'n')
   printf("输入错误!\n");
  else
   break;
 }
 while(1){
  printf("请参照上面的格式输入初始状态(空白位置以0代替):\n");
  k = 0;
  bool error = false;
  memset(used,0,sizeof(used));
  for(i = 0; i < 3; i++){
   for(j = 0; j < 3; j++){
    scanf("%d",&sta[k]);
    ot[i][j] = sta[k];
    if(used[sta[k]]){
     error = true;
    }
    used[sta[k]] = 1;
    temp[k++] = ter[i][j];
   }
  }
  int ts = nxnum(sta);
  int tt = nxnum(temp);
  if(error){
   printf("输入错误(有相同数字出现),请重新输入!\n");
   continue;
  }
  if((ts&1) != (tt&1)){
   printf("从初始状态到不了目标状态,请重新输入。\n");
  }
  else break;
 }
 if(H(ot) == 0){
  printf("所输入状态就是目标状态!\n");
  return 0;
 }
 s = 0;
 for(i = 0; i < 9; i++){
  s = s*10 + sta[i];
 }
 astar(s);
 print(pout);
 printf("第%d步:\n",no);
 for(i = 0; i < 3; i++){
  for(j = 0; j < 3; j++){
   if(ter[i][j] == 0)
    printf("  ");
   else
    printf("%d ",ter[i][j]);
  }
  printf("\n");
 }
 printf("共走了%d步。\n",no);
 return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -