[BZOJ 1054][HAOI 2008]移动玩具(BFS+判重)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1054

真是水题,感谢HAOI送的福利样例23333

裸BFS,用string做判重,会八数码就会这题。

注意由于队列中状态数很多,一定要把队列的数组开大点!!!

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <map>

#define MAXN 5

using namespace std;

map<string,bool>visit;

int tmp[MAXN][MAXN],nowstatus[MAXN][MAXN];
int xx[]={1,-1,0,0},yy[]={0,0,1,-1};

bool inMap(int x,int y)
{
    if(x<1||x>4||y<1||y>4) return false;
    return true;
}

string GetPermutationFromArray()
{
    string ans="";
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            ans+=tmp[i][j]+'0';
    return ans;
}

void GetArrayFromPermutaion(string s)
{
    int p=0;
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            tmp[i][j]=s[p++]-'0';
}

struct node
{
    string status;
    int step;
}q[100000],first,goal;

int h=0,t=0;

int BFS()
{
    q[t++]=first;
    visit[first.status]=true;
    while(h<t)
    {
        node now=q[h++];
        if(now.status==goal.status) return now.step;
        GetArrayFromPermutaion(now.status);
        for(int x=1;x<=4;x++)
            for(int y=1;y<=4;y++)
            {
                if(tmp[x][y]==1) //(x,y)是玩具
                {
                    for(int dir=0;dir<4;dir++)
                    {
                        int tx=x+xx[dir],ty=y+yy[dir];
                        if(!inMap(tx,ty)) continue;
                        if(tmp[tx][ty]==0) //(tx,ty)是空地
                        {
                            node next;
                            next.step=now.step+1;
                            swap(tmp[x][y],tmp[tx][ty]);
                            next.status=GetPermutationFromArray();
                            if(!visit[next.status])
                            {
                                visit[next.status]=true;
                                q[t++]=next;
                            }
                            swap(tmp[x][y],tmp[tx][ty]);
                        }
                    }
                }
            }
    }
    return -1;
}

int main()
{
    string s;
    first.step=0;
    for(int i=1;i<=4;i++)
    {
        cin>>s;
        first.status+=s;
    }
    for(int i=1;i<=4;i++)
    {
        cin>>s;
        goal.status+=s;
    }
    printf("%d\n",BFS());
    return 0;
}



时间: 2024-10-16 01:47:56

[BZOJ 1054][HAOI 2008]移动玩具(BFS+判重)的相关文章

[BZOJ 1042][HAOI 2008]硬币购物(背包+容斥原理)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1042 刚开始搞容斥原理,还很有点吃力,我太弱了... 首先用被类似于背包的DP进行预处理,假设每种硬币个数无限制,求出f[i]=凑出面值i的方案总数. 但是实际上题目中每种硬币个数是有限制的,设四种硬币分别是a.b.c.d,则凑出面值S的方案中超出限制的方案数=a超出限制的方案数+b超出限制的方案数+c超出限制的方案数+d超出限制的方案数-a和b都超出限制的方案数-a和c都超出限

BZOJ 1042 HAOI 2008 硬币购物 容斥原理

题目大意:给出4个硬币的价值和个数限制,求有多少种方法凑成S块钱. 思路:很巧妙的一种想法,用到了4这个非常小的数字.我们可以先不管每个硬币的个数限制,然后跑一次完全背包.之后把不符合的情况去除就行了.方法是,先减去一种硬币超限的数目,然后加上两种硬币超限的数目,然后减去三种硬币超限的数目,然后加上四种硬币超限的个数.当然代码就很丑了.. CODE: #include <cstdio> #include <cstring> #include <iostream> #in

BZOJ 1043 HAOI 2008 下落的圆盘 计算几何

题目大意:给出一些圆盘,他们按照时间顺序相互覆盖,问最后的到的图形的可见圆周的周长是多少. 前言:円盘反对!让我们一起团结起来!赶走円盘! 思路:对于每一个圆盘,只要扫描在它后面出现的圆与它交的部分的并,总周长-相交的并就是剩下能看见的圆周的长度,然后累加到答案中. 对于两个圆的交,我们可以用一个有序数对(x,y)以弧度为单位来表示,这样所有的xy都在0~2π区间之内.求角度就利用余弦定理,见下图: ∠EAC就是我们要求的角.由于我们知道|AE|和|EC|分别是两个圆的半径,|AC|是圆心的距离

BZOJ 1054题解 BFS暴力求解

BZOJ 1054题解 BFS暴力求解 1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1884  Solved: 1033[Submit][Status][Discuss] Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移 动到某人

Keyboarding (bfs+预处理+判重优化)

# #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5$ 个控制键,你可以移动电视屏幕上的光标来打印文本.一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向上与当前位置不同的字符,若不存在则不移动.每次按选择键,则将光标所在位置的字符打印出来. 现在求打印给定文本(要在结尾打印换行符)的最少按键次数. [算法] 1.预处理四个方向能到达的点.

BZOJ 1054 [HAOI2008]移动玩具

直接暴力广搜即可.. [网上有大神说双向广搜速度快,然而直接暴力广搜就可以过了] 队列中的状态用二进制来存储.. 我用了一个比较sb的写法,勿喷qaq 1 #include <queue> 2 #include <cstdio> 3 4 using namespace std; 5 6 unsigned int Start, End; 7 bool M[4][4]; 8 9 const int dx[] = {+0, +0, +1, -1}; 10 const int dy[] =

BFS+Hash(储存,判重) HDOJ 1067 Gap

题目传送门 题意:一个图按照变成指定的图,问最少操作步数 分析:状态转移简单,主要是在图的存储以及判重问题,原来队列里装二维数组内存也可以,判重用神奇的hash技术 #include <bits/stdc++.h> using namespace std; const int MOD = 1e6 + 7; struct Point { int ch[5][9]; int x[4], y[4]; int step; }; bool vis[MOD]; int ha; int get_hash(i

POJ 1101 The Game(BFS+判方向)

    The Game Description One morning, you wake up and think: "I am such a good programmer. Why not make some money?'' So you decide to write a computer game. The game takes place on a rectangular board consisting of w * h squares. Each square might o

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6