poj 3221 Diamond Puzzle 反向bfs

分析:

简单的bfs,但要注意因为输入cases很多,对每个初始状态都搜一遍会超时,其实可以从终止状态反向搜一遍,对搜到的每个状态打表存下即可。

代码:

//poj 3221
//sep9
#include <iostream>
#include <queue>
using namespace std;
int n;
int fac[]={1,1,2,6,24,120,720,5040,40320};
int vis[10000],g[10000];
int pos[8][8];
struct NODE
{
	int s[9];
	int loc;
	int status;
};

int cantor(int s[])
{
    int sum=0;
    for(int i=0;i<7;++i){
        int cnt=0;
        for(int j=i+1;j<7;++j)
            if(s[i]>s[j])
                ++cnt;
        sum+=cnt*fac[7-i-1];
    }
    return sum;
}  

void bfs(NODE start)
{
	queue<NODE> open;
	NODE cur,nxt;
	memset(vis,0,sizeof(vis));
	memset(g,-1,sizeof(g));
	vis[start.status]=1;
	g[start.status]=0;
	open.push(start);
	while(!open.empty()){
		cur=open.front();open.pop();
		int cur_zero_pos=cur.loc;
		for(int i=1;i<=pos[cur_zero_pos][0];++i){
			int nxt_zero_pos=pos[cur_zero_pos][i];
			nxt=cur;
			swap(nxt.s[cur_zero_pos],nxt.s[nxt_zero_pos]);
			nxt.loc=nxt_zero_pos;
			nxt.status=cantor(nxt.s);
			if(vis[nxt.status]==0){
				open.push(nxt);
				g[nxt.status]=g[cur.status]+1;
				vis[nxt.status]=1;
			}
		}
	}
}

int main()
{
	int cases;
	pos[0][0]=3,pos[0][1]=2,pos[0][2]=4,pos[0][3]=6;
	pos[1][0]=2,pos[1][1]=2,pos[1][2]=6;
	pos[2][0]=3,pos[2][1]=0,pos[2][2]=1,pos[2][3]=3;
	pos[3][0]=2,pos[3][1]=2,pos[3][2]=4;
	pos[4][0]=3,pos[4][1]=0,pos[4][2]=3,pos[4][3]=5;
	pos[5][0]=2,pos[5][1]=4,pos[5][2]=6;
	pos[6][0]=3,pos[6][1]=0,pos[6][2]=1,pos[6][3]=5;
	NODE ncur;
	for(int i=0;i<7;++i)
		ncur.s[i]=i;
	ncur.loc=0;
	ncur.status=cantor(ncur.s);
	bfs(ncur);
	scanf("%d",&cases);
	while(cases--){
		char ch[16];
		int s[16];
		scanf("%s",ch);
		for(int i=0;i<7;++i)
			s[i]=ch[i]-'0';
		int cantor_value=cantor(s);
		printf("%d\n",g[cantor_value]);
	}
	return 0;
}
时间: 2024-10-25 08:06:11

poj 3221 Diamond Puzzle 反向bfs的相关文章

POJ 3221 Diamond Puzzle

Description A diamond puzzle is played on a tessellated hexagon like the one shown in Figure 1 below. And in this problem the faces produced by the tessellation are identified as they are numbered in the same figure. If two faces share a side, they a

AOJ 0121 Seven Puzzle(反向BFS+map)

卡了很久的一道题,之前用正向BFS硬缸,结果凉凉,下面是之前错误的代码,仅供自己记录,他人浏览请直接跳过: 1 #include<cstring> 2 #include<iostream> 3 #include<queue> 4 #include<algorithm> 5 #include<cstdio> 6 7 using namespace std; 8 9 int tmaze[2][4]; 10 struct node{ 11 int ma

HDU 1043 Eight(反向BFS+打表+康托展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各个状态记录下来,因为数字太大所以用康托展开将数字离散化. 代码: 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<st

POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路)

POJ 2251 题目大意: 给出一三维空间的地牢,要求求出由字符'S'到字符'E'的最短路径,移动方向可以是上,下,左,右,前,后,六个方向,每移动一次就耗费一分钟,要求输出最快的走出时间.不同L层的地图,相同RC坐标处是相连通的.(.可走,#为墙) 解题思路:从起点开始分别往6个方向进行BFS(即入队),并记录步数,直至队为空.若一直找不到,则困住. /* POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路) */ #include <cstdio> #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

poj 3087 Shuffle&#39;m Up (bfs)

Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of poker chips, S1 and S2, each stack containing C chips. Each stack may contain chips of several

poj 3388 Japanese Puzzle

Description A brand-new Japanese puzzle is coming from the East to strike the world-popular Sudoku game and become an international hit. The rules of this puzzle are kept in secret yet, but the goal is already advertised: given a square grid n × n, w

POJ 2251:Dungeon Master(三维BFS)

Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16178 Accepted: 6268 Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled wit

POJ 1651 Multiplication Puzzle (区间dp)

题目大意:对n个数组成的序列取数,规定最两边不能取,每次取一个a[i],得到 a[l] * a[i] * a[r] 的分数(a[l]是a[i]左边的数,a[r]是a[i]右边的数),并把这个数从序列中移走,求n-2次取数后的得分和的最小值 分析:正着确定状态不好做,不如反着来,设dp[l][r]为向区间[l, r]中填满数所得到分数和的最小值,考虑最近一次填数的位置,不难得出: dp[l][r] = fmin(dp[l][m] + dp[m][r] + a[l] * a[m] * a[r]) (