zoukankan      html  css  js  c++  java
  • 题解——八数码难题

    思路

    由明确的两种状态可以想到

    D(double)BFS即双向BFS

    输入的是个

    283104765
    

    然而 凡是搜索都有个标记即vis[]

    但 按题意3 * 3的地图不好标记(也许用map可以)

    于是直接用一维dir数组改成

    int dir[4] = {1,-3,-1,3};
    

    但九位数也是开不了的

    就有一个cantor展开式

    状态压缩一下

    inline int cantor(int a[])
    {
    	int i,j,ans = 0;
    	for(i = 0;i < 9;i++)
    	{
    		int s = 0;
    		for(j = i + 1;j < 9;j++)
    			if(a[j] < a[i]) s++;
    		ans += s * fac[8 - i];
    	}
    	return ans;
    }
    

    然后就行了 DBFS直接套板子啊

    优化

    其实就上面的好像就可以过了

    但还有个优化

    逆序对有关

    将3 * 3 的图 弄成序列

    可以得出结论:初始状态的逆序对模2必须等于目标状态的逆序对模2,否则无法达成,输出-1

    证明

    可以转为 初始状态无论如何改变其奇偶性不变

    位置图

    1 2 3

    4 5 6

    7 8 9

    将3 * 3 的图 弄成序列

    1 2 3 4 5 6 7 8 9

    注意 0 不算入队列 所以上面实际上是8个

    ~~

    2 8 3

    1 0 4

    7 6 5

    可见 当位置5的0与位置8的6交换会有几种情况

    位置n的数 为方便简写为(n)

    Case1:(6)和(7)中有0个比(8)小

    则逆序对+ 2

    Case2:(6)和(7)中有1个比(8)小

    则逆序对- 1 + 1

    Case2:(6)和(7)中有2个比(8)小

    则逆序对+ 2

    综上逆序对奇偶性不变

    其它交换情况可以类似讨论

    代码

    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int MAXN = 400000;
    int step[2][MAXN],fac[10] = {1,1,2,6,24,120,720,5040,40320,362880};
    bool vis[2][MAXN];
    int dir[4] = {1,-3,-1,3};
    
    //cantor状态压缩
    inline int cantor(int a[])
    {
    	int i,j,ans = 0;
    	for(i = 0;i < 9;i++)
    	{
    		int s = 0;
    		for(j = i + 1;j < 9;j++)
    			if(a[j] < a[i]) s++;
    		ans += s * fac[8 - i];
    	}
    	return ans;
    }
    struct Node
    {
    	int word[9],loc,ca;
    	bool f;
    	void node(int Word[],int LOC,int CA,bool F)
    	{
    		for(int i = 0;i < 9;i++) word[i] = Word[i];
    		loc = LOC,ca = CA,f = F;
    	}
    }Start,order;
    inline int dbfs()
    {
    	queue<Node> q;
    	Start.f = 1,order.f = 0;
    	q.push(Start);
    	q.push(order);
    	int i;
    	while(!q.empty())
    	{
    		Node tmp = q.front();
    		q.pop();
    		if(vis[!tmp.f][tmp.ca])
    			return (step[1][tmp.ca] + step[0][tmp.ca]);
    		int Step = step[tmp.f][tmp.ca];
    		for(i = 0;i < 4;i++)
    		{
    			int poss = tmp.loc + dir[i];
                
                //由于dir数组改了 判断也得改
    			if(0 <= poss&&poss < 9&&(tmp.loc % 3 == poss % 3||tmp.loc / 3 == poss / 3))
    			{
    				swap(tmp.word[tmp.loc],tmp.word[poss]);
    				int nca = cantor(tmp.word);
    				if(!vis[tmp.f][nca])
    				{
    					Node g;
    					vis[tmp.f][nca] = 1;
    					step[tmp.f][nca] = Step + 1;
    					g.node(tmp.word,poss,nca,tmp.f);
    					q.push(g);
    				}
    				swap(tmp.word[tmp.loc],tmp.word[poss]);	
    			}
    		}
    	}
    	return -1;
    }
    
    //优化 求逆序对
    inline int cutdown(int a[])
    {
    	int i,j,q = 0;
    	for(i = 0;i < 9;i++)
    		for(j = i + 1;j < 9;j++)
    			if(a[i] != 0&&a[j] != 0&&a[j] < a[i]) q++;
    	return q;
    }
    int main()
    {
    	int i;
    	for(i = 0;i < 9;i++) 
    	{
    		scanf("%d",&Start.word[i]);
    		if(!Start.word[i]) Start.loc = i;
    	}
    	for(i = 0;i < 9;i++)
    	{
    		scanf("%d",&order.word[i]);
    		if(!order.word[i]) order.loc = i;
    	}
        //优化
    	if(cutdown(Start.word) % 2 != cutdown(order.word) % 2)
    	{
    		printf("-1");
    		return 0;
    	}
    	Start.ca = cantor(Start.word);
    	vis[1][Start.ca] = 1;
    	order.ca = cantor(order.word);
    	vis[0][order.ca] = 1;
    	printf("%d",dbfs());
    	return 0;
    }
    
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/resftlmuttmotw/p/11323219.html
Copyright © 2011-2022 走看看