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(int c[5][9])	{
	int tmp[60], k = 0;
	for (int i=1; i<=4; ++i)	{
		for (int j=2; j<=8; ++j)	{
			tmp[k++] = c[i][j] % 10;
			tmp[k++] = c[i][j] / 10;
		}
	}
	int ret = 0;
	for (int i=0; i<k; ++i)	{
		ret = (ret * 7 % MOD + tmp[i]) % MOD;
	}
	ret = (ret & 0x7fffffff) % MOD;
	return ret;
}

int init(void)	{
	int res[5][9];
	int x[4] = {11, 21, 31, 41};
	for (int i=0; i<4; ++i)	{
		for (int j=1; j<=7; ++j)	{
			res[i+1][j] = x[i]++;
		}
		res[i+1][8] = 0;
	}
	return get_hash (res);
}

void change(Point &v, int x0, int y0, int k)	{
	int a = v.ch[x0][y0-1] + 1;
	for (int i=1; i<=4; ++i)	{
		for (int j=2; j<=8; ++j)	{
			if (v.ch[i][j] == a)	{
				v.x[k] = i;	v.y[k] = j;
				swap (v.ch[x0][y0], v.ch[i][j]);
				return ;
			}
		}
	}
}

int BFS(Point &p)	{
	memset (vis, false, sizeof (vis));
	int sh = get_hash (p.ch);
	vis[sh] = true;
	queue<Point> que;	que.push (p);
	while (!que.empty ())	{
		Point u = que.front ();	que.pop ();
		int uh = get_hash (u.ch);
		if (uh == ha)	{
			return u.step;
		}
		for (int i=0; i<4; ++i)	{
			int x = u.x[i], y = u.y[i];
			if (y == 1 || u.ch[x][y] % 10 == 7)	continue;
			Point v = u;
			change (v, x, y, i);
			int vh = get_hash (v.ch);
			if (vis[vh])	continue;
			vis[vh] = true;	v.step++;
			que.push (v);
		}
	}

	return -1;
}

int main(void)	{
	ha = init ();
	int T;	scanf ("%d", &T);
	while (T--)	{
		Point p;	p.step = 0;
		for (int i=1; i<=4; ++i)	{
			p.ch[i][1] = 0;
		}
		for (int i=1; i<=4; ++i)	{
			for (int j=2; j<=8; ++j)	{
				scanf ("%d", &p.ch[i][j]);
			}
		}
		for (int i=1; i<=4; ++i)	{
			for (int j=2; j<=8; ++j)	{
				if (p.ch[i][j] == 11)	{
					swap (p.ch[1][1], p.ch[i][j]);
					p.x[0] = i;	p.y[0] = j;
				}
				else if (p.ch[i][j] == 21)	{
					swap (p.ch[2][1], p.ch[i][j]);
					p.x[1] = i;	p.y[1] = j;
				}
				else if (p.ch[i][j] == 31)	{
					swap (p.ch[3][1], p.ch[i][j]);
					p.x[2] = i;	p.y[2] = j;
				}
				else if (p.ch[i][j] == 41)	{
					swap (p.ch[4][1], p.ch[i][j]);
					p.x[3] = i;	p.y[3] = j;
				}
			}
		}
		int ans = BFS (p);
		printf ("%d\n", ans);
	}

	return 0;
}

  

时间: 2024-10-07 05:31:32

BFS+Hash(储存,判重) HDOJ 1067 Gap的相关文章

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进制的

北京网络赛G BOXES 状态压缩+有序BFS+高维数组判重

#include <bits/stdc++.h> using namespace std; int vis1[7]; int vis2[7][7]; int vis3[7][7][7]; int vis4[7][7][7][7]; int vis5[7][7][7][7][7]; int vis6[7][7][7][7][7][7]; int vis7[7][7][7][7][7][7][7]; struct node{ int a[7]; int step; }; bool check(in

hdu 4821 字符串hash+map判重 String (长春市赛区I题)

http://acm.hdu.edu.cn/showproblem.php?pid=4821 昨晚卡了非常久,開始TLE,然后优化了之后,由于几个地方变量写混.一直狂WA.搞得我昨晚都失眠了,,. 这几次hash军写错的变量--tmp=(j==m-1)?ah[j]:(ah[j]-ah[j-m]*base[m]);  外层循环变量是i,我写的字符串hash的几题都写成tmp=(i==0)? ah[j]:(ah[j]-ah[j-m]*base[m]); 二逼啊 题目大意: 给定一个字符串(最长10^

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,

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 &

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

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的结果进行判重,只保留相同余数的最小数