• 93 魔板


    93 魔板

    作者: xxx时间限制: 1S章节: 宽度优先搜索

    问题描述 :

    在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:

    1  2  3  4  
    8  7  6  5  
    

    我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。

    这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):

    “A”:交换上下两行;

    “B”:将最右边的一列插入最左边;

    “C”:魔板中央四格作顺时针旋转。

    下面是对基本状态进行操作的示范:

    A: 8 7 6 5
    1 2 3 4

    B: 4 1 2 3
    5 8 7 6

    C: 1 7 2 4
    8 6 3 5

    对于每种可能的状态,这三种基本操作都可以使用。 你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。

    输入说明 :

    只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间)不换行,表示目标状态。

    注意,数据输入是顺时针的。即如果要输入目标状态:

    8 7 6 5
    1 2 3 4

    则应该输入: 8 7 6 5 4 3 2 1

    输出说明 :

    第一行: 包括一个整数,表示最短操作序列的长度。

    第二行: 操作序列,用字符串表示,除最后一行外,每行输出60个字符。如果有多个操作序列满足要求,则输出在字典序中最小的那个。

    输入范例 :
    2 6 8 4 5 7 3 1
    输出范例 :
    7
    BCABCCB

    #include <iostream>
    #include <string>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int poWn[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//阶乘
    string pStr[50000];//存放排列字符串
    bool p[50000] = { 0 };
    struct STR
    {
    	string res,step;
    }n,tmp;
    
    int KT(string str)//康特展开式 判断数列排位
    {
    	int len = (int)str.length();
    	int sum = 0;
    	for (int i = 0; i < len; i++)
    	{
    		int min=0;
    		for (int j = i + 1; j < len; j++)
    		{
    			if (str[i]>str[j]) min++;
    		}
    		sum += min*poWn[len - i - 1];
    	}
    	return sum + 1;
    }
    
    void changeA(string &str)//A操作
    {
    	reverse(str.begin(), str.end());
    }
    
    void changeB(string &str)//B操作
    {
    	int len = (int)str.length();
    	reverse(str.begin(),str.begin()+3);
    	reverse(str.begin(), str.begin() + 4);
    	reverse(str.begin() + 5, str.end());
    	reverse(str.begin() + 4, str.end());
    }
    
    void changeC(string &str)//B操作
    {
    	int temp = str[6];
    	str[6] = str[5];
    	str[5] = str[2];
    	str[2] = str[1];
    	str[1] = temp;
    }
    
    void bfs()
    {
    	string str = "12345678", panel = "";
    	n.res = str; n.step = panel;
    	p[KT(str)] = true;
    	queue<STR> q;
    	q.push(n);
    	while (!q.empty())
    	{
    		n = q.front(); q.pop();
    		tmp = n;//用来还原
    
    		changeA(tmp.res);
    		int kt = KT(tmp.res);
    		if (p[kt] == false)
    		{
    			tmp.step += "A";
    			pStr[kt] = tmp.step;
    			q.push(tmp);
    			p[kt] = true;
    		}
    		tmp = n;
    
    		changeB(tmp.res);
    		kt = KT(tmp.res);
    		if (p[kt] == false)
    		{
    			tmp.step += "B";
    			pStr[kt] = tmp.step;
    			q.push(tmp);
    			p[kt] = true;
    		}
    		tmp = n;
    
    		changeC(tmp.res);
    		kt = KT(tmp.res);
    		if (p[kt] == false)
    		{
    			tmp.step += "C";
    			pStr[kt] = tmp.step;
    			q.push(tmp);
    			p[kt] = true;
    		}
    	}
    }
    
    int main()
    {
    	bfs();
    	/*string str ="12345678",sss; // 测试
    	sss = str;
    	changeA(sss);
    	cout << sss << endl;  //87654321
    	sss = str;
    	changeB(sss);
    	cout << sss << endl; //41236785
    	sss = str;
    	changeC(sss);
    	cout << sss << endl; // 17245368
    	*/
    	string str,str1;
    	for (int i = 0; i < 8; i++)
    	{
    		cin >> str1; str += str1;
    		getchar();
    	}
    	//cout << str << endl;
    	int kt = KT(str);
        string res = pStr[kt];
        cout << (int)res.length() << endl << res << endl;
    	return 0;
    }
    
    Yesterday is history,tomorrow ismystery,but today is a gift!That why it is called Present!
  • 相关阅读:
    Gym
    Gym 100712H
    CodeForces
    CodeForces
    P1103 书本整理(DP)
    P1435 回文子串(最长公共子序列)
    P1095 守望者的逃离(线性DP)
    P1077 摆花(背包)
    P1832 A+B Problem(再升级)
    P1757 通天之分组背包(分组背包)
  • 原文地址:https://www.cnblogs.com/VictorierJwr/p/12878526.html
Copyright © 2020-2023  润新知