HDU 1067 HASH判重BFS

给出起始状态如:

问最少多少步操作可以变为:

每次操作只能把一个数字放到某个空格,不能交换两个数字的位置

hash判重模板mark一个

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

const int mod=1000007;
int aim[4][8]=
{
    {11,12,13,14,15,16,17},
    {21,22,23,24,25,26,27},
    {31,32,33,34,35,36,37},
    {41,42,43,44,45,46,47}
};
struct node
{
    int a[4][8],t;
}ncur;
int used[1000008];
int get_hash(node b)
{
    int mark[70],i,j,k;
    __int64 temp;
    memset(mark,0,sizeof(mark));
    k=0;
    for (i=0;i<4;i++)
        for (j=0;j<8;j++)
        {
            mark[k++]=b.a[i][j]/10;
            mark[k++]=b.a[i][j]%10;
        }
    temp=0;
    for (i=0;i<k;i++)
        temp=temp*7+mark[i];
    temp=temp&0x7fffffff;
    temp%=mod;
    return temp;
}

int ok(node b)
{
    int i,j;
    for (i=0;i<4;i++)
        for (j=0;j<7;j++)
        if (b.a[i][j]!=aim[i][j]) return 0;
    return 1;
}

node change(node b,int w)
{
    node key;
    int i,j;
    key=b;
    for (i=0;i<4;i++)
        for (j=0;j<=7;j++)
        if (key.a[i][j]==w+1)
        {
            key.a[i][j]=0;
            return key;
        }
}
int BFS()
{
    queue<node>q;
    node cur,next;
    int i,j,temp;
    ncur.t=0;
    q.push(ncur);
    memset(used,0,sizeof(used));
    temp=get_hash(ncur);
    used[temp]=1;

    while (!q.empty())
    {
        cur=q.front();
        q.pop();
        if (ok(cur)==1) return cur.t;
        for (i=0;i<4;i++)
            for (j=1;j<8;j++)
            if (cur.a[i][j]==0 && cur.a[i][j-1]!=0 && cur.a[i][j-1]%10!=7)
            {
                next=change(cur,cur.a[i][j-1]);
                next.a[i][j]=next.a[i][j-1]+1;
                next.t=cur.t+1;
                temp=get_hash(next);
                if (used[temp]==0)
                {
                    used[temp]=1;
                    q.push(next);
                }
            }
    }
    return -1;
}

int main()
{
    int Case,i,j;
    scanf("%d",&Case);
    while (Case--)
    {
        for (i=0;i<4;i++)
            for (j=1;j<=7;j++)
            {
                scanf("%d",&ncur.a[i][j]);
                if (ncur.a[i][j]%10==1)
                {
                    ncur.a[ncur.a[i][j]/10-1][0]=ncur.a[i][j];
                    ncur.a[i][j]=0;
                }
            }
        printf("%d\n",BFS());
    }
    return 0;
}
时间: 2024-10-15 13:12:45

HDU 1067 HASH判重BFS的相关文章

HDU ACM 1067 Gap-&gt;BFS+HASH判重

题意:初始状态为左边空一行,数字在右边28个格子.末态要按一副卡片在一行顺序牌,即第一行为11-17,第二行21-27,....,可以通过四个空格来转移卡片,问从初始状态到末态最少要多少步. 分析: 1.每次操作只能把一个数字放到某个空格,不能交换两个数字的位置. 2.用的是再哈希法hash =(v+10)%M来处理冲突. 3.空格的左边为空或者数字的末尾为7则不能填充. 4.填充空格要找比他左边大1的数来填充. #include<iostream> #include<queue>

11198 - Dancing Digits(BFS + hash判重)

题目:11198 - Dancing Digits 题目大意:每组数据给出8个数字,可能正可能负.要求最后将这8个数字按照数字绝对值从小到大的排序.排序的规则是让某个数字a邀请另一个数字b跳舞,这样a就可以插到b的左边或是右边,a能邀请b跳舞,则a* b <0 ,且a+b要是素数.题目问给出一组数据问能否通过邀请跳舞来排序,能的话就输出最少的邀请次数,否则输出-1. 解题思路:这题一开始竟然想着dfs,但是后面发现,这样的判断树可以是无限大,因为可以a邀请完b,然后b在邀请a,这样一来一回有可能

codevs 1004 四子连棋 BFS、hash判重

004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input

洛谷 P1379 八数码难题 Label:判重&amp;&amp;bfs

特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数

HDU 1067 Gap BFS+Hash

感觉可以用bfs暴力,一开始写了一个很暴力的bfs,hash判重,本地跑了几组数据发现至少要2s才能过,交上去估计要TLE,试探性的交了一发1A了,原来时限是10s,我看成1s了,真是逗逼...还一直不敢写 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include &

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

hdu 5012 bfs --- 慎用STL 比如MAP判重

http://acm.hdu.edu.cn/showproblem.php?pid=5012 发现一个问题 如果Sting s = '1'+'2'+'3'; s!="123"!!!!!!  而是有乱码 先贴一份自己的TLE 代码, 超时应该是因为: 1.cin 2.map判重 map find太花时间 3.string花时间 4.其实不用两个都旋转,只要旋转一个就行,这样可以省下很多时间 包括少用了make_pair pair的判重等等....哎  二笔了  太暴力了 #include

HDU 4474&amp;&amp;POJ 1465 BFS&amp;&amp;余数判重

两道题只是输入输出格式略有不同 给出n,m,m个数 要求生成一个数x,是n的倍数,并且只由这M个数构成(或不能含有这M个数中的任意一个),求最小的x,没有则输出-1(0): BFS找每一个满足n的倍数的数,用余数判重优化 对于给定两个数A,B,如果A和B模N都相同,设为C,即: A=x*N+C B=y*N+C 那么如果在A后面加上一个数字能够被N整除,则在B后面加上这个数字也肯定可以被N整除 即:(A*10+X)%N==(B*10+X)%N 因此可以利用模N的结果进行判重,只保留相同余数的最小数

hdu 1226 超级密码 bfs+取余判重

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2808    Accepted Submission(s): 897 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的