标签:
Following the success of the magic cube, Mr. Rubik invented its planar version, called magic squares. This is a sheet composed of 8 equal-sized squares:
1 | 2 | 3 | 4 |
8 | 7 | 6 | 5 |
In this task we consider the version where each square has a different color. Colors are denoted by the first 8 positive integers. A sheet configuration is given by the sequence of colors obtained by reading the colors of the squares starting at the upper left corner and going in clockwise direction. For instance, the configuration of Figure 3 is given by the sequence (1,2,3,4,5,6,7,8). This configuration is the initial configuration.
Three basic transformations, identified by the letters `A‘, `B‘ and `C‘, can be applied to a sheet:
Below is a demonstration of applying the transformations to the initial squares given above:
A: |
|
B: |
|
C: |
|
All possible configurations are available using the three basic transformations.
You are to write a program that computes a minimal sequence of basic transformations that transforms the initial configuration above to a specific target configuration.
A single line with eight space-separated integers (a permutation of (1..8)) that are the target configuration.
2 6 8 4 5 7 3 1
Line 1: | A single integer that is the length of the shortest transformation sequence. |
Line 2: | The lexically earliest string of transformations expressed as a string of characters, 60 per line except possibly the last line. |
7 BCABCCB
题意:一块模板有三种操作:分别是A、B、C,A操作时交换上下两行,B操作时将最后一列插在最前面,C操作时将中间四个数顺时针旋转一下。告诉你初始状态和目标状态,求最少多少次操作可以变化到目标状态,并且输出其操作序列。输入的目标状态时按顺时针输入的。
思路:
就是 BFS咯。
对于判重 下面用的是map直接暴力判断。另外一种way就是 康托展开 得到一个Hash值。
看这个值出现过没有就OK了。
用康托展开 不仅把空间缩小到了 n!(n为字符串长度,这里是8) 而且还很快也。
推荐~
至于康托展开:
X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,(其中a[i]为当前未出现的元素中是排在第几个(从0开始))(网上十分复杂的说法)
(其实就是 比当前位置的数 小&&未出现过 的数 一共有多少个)(实质就是 在全排列中 比当前排列小的一共有多少个 )。这就是康托展开。 (将Hash值+1 就是这个排列自己的序号了(是第几小)(从1开始))
Contor 代码:
const int FRAC[MSQUARE_SIZE]= {1, 1, 2, 6, 24, 120, 720, 5040};//这个数组保存的是 各个上述的 阶层
//此处默认字符串长度就是8
inline int Contor(string &v) { int ans = 0; for (int i = 0; i < 8; i++) { int tmp = 0; for (int j = i+1; j < 8; j++) if (v[i] > v[j]) ++tmp;
//统计比当前位置的数 小&&未出现过的数 有多少个。
//当然也就等于 在当前位置后面 比当前位置的数 小的数的个数
ans += tmp * FRAC[7-i]; } return ans+1; }
下面是题目代码 :
/* ID:Andy Chen LANG: C++ PROG: msquare */ #include<iostream> #include<cstdio> #include<queue> #include<string> #include<map> #define MAXN 10000 using namespace std; struct state { string s,ans; int step; }; char ans[MAXN]; map<string,bool> vis; string tail; string opA(string a) { int i; for(i=0;i<4;i++) swap(a[i],a[i+4]); return a; } string opB(string a) { char t; t=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=t; t=a[7];a[7]=a[6];a[6]=a[5];a[5]=a[4];a[4]=t; return a; } string opC(string a) { char t; t=a[1];a[1]=a[5];a[5]=a[6];a[6]=a[2];a[2]=t; return a; } void BFS() { bool flag; state t,tt; t.step=0;t.s="12348765";t.ans=""; queue<state>Q; Q.push(t); vis[t.s]=true; while(!Q.empty())//以下的vis 可以替换为 康托展开的Hash值.判断 { t=Q.front();Q.pop(); if(t.s==tail) { cout<<t.step<<endl<<t.ans<<endl; return ; } tt.ans=t.ans; tt.step=t.step+1; flag=false; tt.s=opA(t.s); if(!vis[tt.s]) { vis[tt.s]=true; tt.ans+=‘A‘; Q.push(tt); flag=true; } tt.s=opB(t.s); if(!vis[tt.s]) { vis[tt.s]=true; if(!flag) tt.ans+=‘B‘; else tt.ans[t.step]=‘B‘; Q.push(tt); flag=true; } tt.s=opC(t.s); if(!vis[tt.s]) { vis[tt.s]=true; if(!flag) tt.ans+=‘C‘; else tt.ans[t.step]=‘C‘; Q.push(tt); } } } int main() { freopen("msquare.in","r",stdin); freopen("msquare.out","w",stdout); int i; string t; for(i=1;i<=8;i++) { cin>>t;tail+=t; } swap(tail[4],tail[7]); swap(tail[5],tail[6]);//因为是顺时针输入,所以需要手动交换一下位置。 BFS(); return 0; }
标签:
原文地址:http://www.cnblogs.com/cherry231/p/5189095.html