/*1151. 魔板
初始状态
1 2 3 4
8 7 6 5
给定一个状态,在指定步骤内通过A、B、C操作到达目标态
定义一个状态数组,头指针fp指向当前的父节点操作,rp
指向子节点操作。判断是否加入子节点序列时:判重! 扫描
整个数组,若出现重复状态则跳过,对每个父节点都有三个
操作,符合条件的进入队列,rp依次后移,fp完成三个操作
后也fp++
利用康托展开记录每种状态出现的位置,即通过康托展开
后可以知道该状态是第几大的数即可马上定位到该位置,
位置访问信息用一个数组记录即可。
康托展开方法(一种特殊的哈希函数)
例如一个123的序列,求321在其全排列中排第几大的数。
首先3, 那么第二位数可以是1或2,则有2*2! = 4个比他小的数,
然后看第二位2,比他小的数有1,则有1*1! = 1 所以有4+1=5个
321小的数,也就是说它是第6大的数。
*/
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;
int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //8!的阶乘表
bool isvisit[50000];
struct state{
int x;
int y;
string op;
};
/*
康托展开
*/
int cantor(long n)
{
int tmp[8];
int cnt;
for (int i = 7; i >= 0; i--)
{
tmp[i] = n%10;
n /= 10;
}
for (int i = 0; i < 7; i++)
{
cnt = 0;
for (int j = i+1; j < 8; j++)
if (tmp[i] >tmp[j]) cnt++;
n += fact[8-i-1] * cnt;
}
return n;
}
void OPA(int &x, int &y)
{
int temp = y;
y = x;
x = temp;
}
void OPB(int &x, int &y)
{
x = x%10 * 1000 + x/10;
y = y%10 * 1000 + y/10;
}
void OPC(int &x, int &y)
{
int x1 = x/1000;
int x2 = (x - x1*1000)/100;
int x3 = (x - x1*1000 - x2*100)/10;
int x4 = x - x1*1000 - x2*100 - x3*10;
int y1 = y/1000;
int y2 = (y - y1*1000)/100;
int y3 = (y - y1*1000 - y2*100)/10;
int y4 = y - y1*1000 - y2*100 - y3*10;
x = x1*1000 + y2*100 + x2*10 + x4;
y = y1*1000 + y3*100 + x3*10 + y4;
}
int main()
{
int n;
int x, y;
int x1,x2,x3,x4, y1,y2,y3,y4;
state qm[81000];
char opresult[300];
n = 0;
char op[3] = {'A', 'B', 'C'};
while(cin >> n && n != -1){
memset(isvisit, false, sizeof(isvisit));
cin >> x1 >> x2 >> x3 >> x4 >> y1 >> y2 >> y3 >> y4;
x = x1*1000+x2*100+x3*10+ x4;
y = y1*1000+y2*100+y3*10+ y4;
int tempx;
int tempy;
int fp=0;
int rp=1;
state init = {1234, 8765, ""};
qm[0] = init;
bool flag = true;
while(fp!=rp){
if(qm[fp].op.length()>n)
{
cout << -1 << endl;
break;
}
tempx = qm[fp].x;
tempy = qm[fp].y;
if(qm[fp].x == x && qm[fp].y == y){
cout << qm[fp].op.length() << " " << qm[fp].op << endl;
break;
}
for(int i=0; i<3 && flag; i++){
tempx = qm[fp].x;
tempy = qm[fp].y;
state temp;
if(op[i] == 'A')
{ OPA(tempx, tempy);
temp.op= qm[fp].op +"A";
}
if(op[i] == 'B')
{ OPB(tempx, tempy);
temp.op= qm[fp].op +"B";
}
if(op[i] == 'C')
{ OPC(tempx, tempy);
temp.op= qm[fp].op +"C";
}
temp.x = tempx;
temp.y = tempy;
if (!isvisit[cantor(tempx * 10000+ tempy)])
{
isvisit[cantor(tempx * 10000+ tempy)] = true;
qm[rp] = temp;
rp++;
}
}
fp++;
}
}
//system("pause");
return 0;
}
Sicily 1151. 魔板
最新推荐文章于 2018-12-30 14:39:50 发布