提升coding能力------搜索专题(3)-----poj 1077

pku 1077 Eight

题目地址:http://poj.org/problem?id=1077

题目大意:

经典的八数码问题,给你一个3*3,其中一个数位x的图,问是否能通过移动x,来使图形成为一个

123

456

78x

这样图形,可以的话,输出x 的移动路径,经典的BFS。

详细分析:

这边先点一下,以后详细填坑。

这边的话需要用到康托展开,康拓展开也可以看成一种hash函数,关键是得用一种映射方法,把你当前的搜索状态(我猜是一个图),映射为一个值,便于判断是否搜索过,可以用来减少判重时间的同时还可以避免不必要的搜索

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
#define aim  1 //目标图形对应的cantor值
struct Node
{
    int Map[9];
    ll val; //康拓展开对应的值
    int x;

};
char s[100];
ll ans[9] ={1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dirc[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
char opt[4] = {'d', 'u', 'l', 'r'};
int vis[500005];
int pre[500005];
char path[500005];
ll Cantor(Node& t)
{
    ll ret = 0;
    for(int i = 0 ;i < 9; i++)
    {
        int cnt = 0;
        for(int j = i + 1 ; j < 9 ;j++ )
        {
            if(t.Map[j] < t.Map[i])
                cnt++;
        }

        ret += cnt* ans[ 8 - i ];
    }

    return ret + 1;
}
int BFS(Node& T) //找初始点到目标节点的最短路径
{
    queue<Node> q;

    Node temp , Front ;
    temp = T;
    vis[temp.val] = 1;
    q.push(temp);

    while(!q.empty())
    {
        Front = q.front();
        q.pop();

        if(Front.val == aim)
        {
              return 1;
        }

        for(int i = 0 ;i < 4; i++)
        {

            temp = Front;
            int pos_x = temp.x/3;
            int pos_y = temp.x%3;

            pos_x += dirc[i][0];
            pos_y += dirc[i][1];

            if( pos_x>=0 && pos_x <3 && pos_y >=0 && pos_y <3 )
            {
                swap( temp.Map[pos_x*3 + pos_y], temp.Map[temp.x]);

                ll can_val = Cantor(temp);

                if(!vis[can_val])
                {

                    temp.val = can_val;
                    temp.x = pos_x*3 + pos_y;
                    vis[can_val] = 1;
                    pre[temp.val] = Front.val;
                    path[temp.val] = opt[i];
                    q.push(temp);


                }

             }



         }


     }

     return 0;
}


void show_path(int i)
{
    if(i == 0)
        return ;

    show_path( pre[i] );

    if( pre[i] != 0 )
      cout <<  path[i];

}


int main()
{
   Node First;
   while(gets(s))
   {
       memset(vis,0,sizeof(vis));
       int index = 0;
       for(int i = 0 ;i < strlen(s); i++) //二维数组用一维存储
       {
           if(s[i] >='1' && s[i] <='8')
              First.Map[ index++ ] = s[i] -'0';
           else if(s[i] == 'x')
           {
              First.x = index;
              First.Map[index++ ] = 9;

           }
       }


      First.val = Cantor(First) ;
      pre[First.val] = 0;

       /*
       cout << First.val << endl;
       cout << First.x << endl;
       for(int i = 0 ;i < 9 ;i++)
          cout << First.Map[i] << endl;
          */


      if( BFS(First) )
      {

          show_path(1);
          cout << endl;
      }
      else
          cout << "unsolvable"<< endl;

       // cout << pre[1] << endl;

       //cout << "have done" << endl;



   }

   return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值