HDU 3567 BFS+预处理

HDU 1043的加强版

8数码问题

给出8数码问题的两种状态,求从A状态到B状态的最优解,数据保证有解,若有多解,输出最短且字典序最小的。

基本思路和1043的差不多,只不过这次要预处理出来9种情况的BFS

即:

BFS(0,"012345678");

BFS(1,"102345678");

BFS(2,"120345678");

BFS(3,"123045678");

BFS(4,"123405678");

BFS(5,"123450678");

BFS(6,"123456078");

BFS(7,"123456708");

BFS(8,"123456780");

然后对于每次读入的A状态根据相应的0位置,对照BFS的表进行映射,转化为1043题型的搜索。

#include "stdio.h"
#include "string.h"
#include "queue"
#include "string"
using namespace std;

const int dir[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
const char indexs[]="dlru";
const int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
char path[10][500010];
int time[10][500010],pri[10][500010],used[500010];

struct node
{
    int status,loc,t;
    int s[9];
};

int Cantor(int b[])
{
    int i,j,sum,cnt;
    sum=0;
    for (i=0;i<=8;i++)
    {
        cnt=0;
        for (j=i+1;j<=8;j++)
            if (b[i]>b[j])
            cnt++;
        sum+=cnt*fac[9-i-1];
    }
    return sum+1;
}
void BFS(int w,char s[])
{
    queue<node>q;
    node cur,next;
    int i,x,y,xx,yy;
    for (i=0;i<=8;i++)
        cur.s[i]=s[i]-'0';
    cur.loc=w;
    cur.t=0;
    cur.status=Cantor(cur.s);
    memset(used,0,sizeof(used));
    used[cur.status]=1;
    q.push(cur);
    pri[w][cur.status]=-1;
    while (!q.empty())
    {
        cur=q.front();
        q.pop();

        x=cur.loc/3;
        y=cur.loc%3;
        for (i=0;i<4;i++)
        {
            xx=x+dir[i][0];
            yy=y+dir[i][1];
            if (xx<0 || xx>2 || yy<0 || yy>2) continue;
            next=cur;
            next.loc=xx*3+yy;
            next.s[cur.loc]=next.s[next.loc];
            next.s[next.loc]=0;
            next.status=Cantor(next.s);
            if (used[next.status]==0)
            {
                used[next.status]=1;
                next.t++;
                path[w][next.status]=indexs[i];
                pri[w][next.status]=cur.status;
                time[w][next.status]=next.t;
                q.push(next);
            }
        }
    }
}

void output(int w,int key)
{
    if (pri[w][key]==-1) return ;
    output(w,pri[w][key]);
    printf("%c",path[w][key]);

}
int main()
{
    int T,key,j,i,Case,status;
    int a[10],b[10];
    char s1[10],s2[10];
    BFS(0,"012345678");
    BFS(1,"102345678");
    BFS(2,"120345678");
    BFS(3,"123045678");
    BFS(4,"123405678");
    BFS(5,"123450678");
    BFS(6,"123456078");
    BFS(7,"123456708");
    BFS(8,"123456780");
    scanf("%d",&T);
    Case=0;
    while (T--)
    {
        Case++;
        scanf("%s%s",s1,s2);
        if (strcmp(s1,s2)==0)
        {
            printf("Case %d: 0\n\n",Case);
            continue;
        }

        for (i=0,j=0;i<=8;i++)
        if (s1[i]=='X') { key=i; a[0]=0;}
        else a[s1[i]-'0']=++j;

        for (i=0;i<=8;i++)
        if (s2[i]=='X') b[i]=a[0];
        else b[i]=a[s2[i]-'0'];

        status=Cantor(b);

        printf("Case %d: %d\n",Case,time[key][status]);
        output(key,status);
        printf("\n");
    }
    return 0;
}
时间: 2024-07-30 23:01:29

HDU 3567 BFS+预处理的相关文章

HDU 3533 Escape(BFS+预处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533 题目大意:给你一张n* m的地图,人在起点在(0,0)要到达终点(n,m)有k(k<=100)座炮台,每座炮台都有各自的发射方向.发射周期和发射速度,每隔一段时间会发射一定速度的炮弹,人每秒可以选择停在原地或者往上下左右走,问是否能在时间d之内安全到达终点.如果可以,请输出最短时间. 解题思路:BFS+预处理,分为以下几点: ①预处理,用step[x][y][t]记录(x,y)在时间t是否被炮

HDU 3567 Eight II(八数码 II)

p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-size: 10.5000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: center; font-family: 宋体; color: rgb(26,92,200); font-weight: bold; fo

hdu 1175 bfs 转弯题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 和之前的1728类似.就是判断转弯数,建立一个用于记录转弯数的数组.. 还有就是对于特殊情况要进行考虑,比如起点与终点相同的情况,对于本题来说是不可以消去的应该输出NO.还有就是起点或终点是零这也是不行的,因为0代表没有棋子... 还有在判断能不能走的时候要小心,对于判断条件一定要小心,不要图赶快写.. 错误的地方都写在注释中了.. 代码: // hdu 1175 bfs 转弯数 //1.起点

Saving Princess claire_(hdu 4308 bfs模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=4308 Saving Princess claire_ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2305    Accepted Submission(s): 822 Problem Description Princess claire_ wa

HDU 1072 bfs

Nightmare Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7083    Accepted Submission(s): 3409 Problem Description Ignatius had a nightmare last night. He found himself in a labyrinth with a tim

hdu 1252 BFS

1 /* 2 题意:给出一个m*m矩阵表示的完全图,且每个点都有自环,每条边都有一种颜色:有三个玩家ABC的三张纸片分别初始在 3 某三个位置(可以重叠),纸片可以沿着边走一步,可以走的路径的规则为:若A要走到某个点i,则A-i的颜色要和B-C的颜 4 色相同:问最少要走多少步.(题意太难懂了,看了别人的说明才弄懂了题意) 5 6 题解:BFS 7 首先初步分析题意似乎很难用图论来解决,那么就是搜索/DP/数据结构,然后从搜索方面去思考的话,就是要找状态,然 8 后初步列出所有信息,三个点得位置

poj_3669_Meteor Shower(BFS+预处理)

http://poj.org/problem?id=3669 /*思路:BFS+预处理 先预处理会爆炸的区域,BFS,遇到-1则结束*/ #include <iostream> #include <queue> #include <algorithm> using namespace std; int visit[1001][1001]; int dx[5] = {0,0,1,0,-1}; int dy[5] = {0,1,0,-1,0}; typedef struct

poj3026Borg Maze(bfs预处理+最小生成树)

题目链接: 啊哈哈,点我点我 思路: 首先把图中的A S预处理出来,然后对这些点逐一做bfs找到这些点到其它点的最短路径,然后建图完毕也用最小生成树的prim算法或者kruscal算法求出连接所有点的最短距离..不知道为嘛用dis数组去维护为什么会超时,而在结构体里面用step数组却可以过,我也不知道为什么,纠结了很多天..我把错误的代码贴出来,希望各位帮我找出原因,不胜感激... 题目: Borg Maze Time Limit: 1000MS   Memory Limit: 65536K T

hdu 4707 bfs

bfs基础算法水题 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include<queue> using namespace std; const int Max = 1e5+50; int dist[Max]; vector<int> t