0. 前言
打了两年的百度之星,都没进决赛。我最大的感受就是还是太弱,总结起来就是:人弱就要多做题,人傻就要多做题。
题目还是按照分类做可能效果比较好,因此,就有了做几个系列的计划。这是系列中的第一个,解决OJ中有关魔方的问题。

1. 概述
魔方大概会涉及两类算法:搜索和模拟。这里的搜索方式一般是双广或者bfs+剪枝,因为双广基本上就可以把题目都解了,所以我也没去
考虑A*。我自身不会玩儿魔方,因此剪枝策略也就两种,不过效果还是很好的。模拟就相对简单,仅需要了解几种旋转的方式基本上是可解。
搜索过程中存在状态爆照问题,因为对于同一个魔方从不同的角度观察得到的抽象数据类型可能不尽相同,但是状态却等价。因此,
很多题需要找到所有可能等价的状态,这其实也是一堆排列。

写魔方旋转以及等价状态,我没有什么特别好的办法。不过由给定的顺时针,可以得到相应的逆时针;由正立状态及倒立状态的映射关系,可以
仅仅通过描述正立排列迅速得到倒立状态。

魔方问题的关键就在于剪枝,双广别写萎了,以及状态等价。

2. 题目
2.1 HDOJ 4801
这是一道2阶魔方,前面做过题解,请参考【HDOJ】4801 Pocket Cube 的几种解法和优化。

2.2 HDOJ 5292
题目大意是给定任何的2阶魔方,需要判定该魔方能否复原。因为这个题目的case范围是$10^4$,所以直接在网上找的结论。具体缘由不清楚。

 /* 5292 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 int a[][]={
,,,,,,-,,,,,
,,,,-,,,,,,,
-,,,,,,,,-,,,
,,-,,,,,,,,-,
,,,,,,-,,,,,
,,,,-,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,,
}; int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char op[]; scanf("%d", &t);
rep(tt, , t+) {
getchar();
int sum = ;
rep(i, , ) {
gets(op);
int len = strlen(op);
#ifndef ONLINE_JUDGE
puts(op);
#endif
rep(j, , len) {
if (op[j]=='y' || op[j]=='w')
sum += a[i][j];
}
}
printf("Case #%d: ", tt);
puts(sum%== ? "YES":"NO");
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

2.3 HDOJ 3549
同样是一道2阶魔方,求由此时情况通过一定的操作序列实现复原。找到这样一个操作序列。
这题目是很早以前解掉的,基本算法是IDA*。启发式策略是至少经过多少次旋转能实现复原,这个策略是贪心的,实际操作可能多余这个H值。
因为2阶魔方大概10几步可能就解掉了,因此这算法性能还算不错。

 /* 3459 */
#include <cstdio>
#include <cstring>
#include <cstdlib> #define MAXN 10
#define MAXL 1005 #define U0 map[0][2]
#define U1 map[0][3]
#define U2 map[1][3]
#define U3 map[1][2] #define F0 map[2][2]
#define F1 map[2][3]
#define F2 map[3][3]
#define F3 map[3][2] #define R0 map[2][4]
#define R1 map[2][5]
#define R2 map[3][5]
#define R3 map[3][4] #define L0 map[2][0]
#define L1 map[2][1]
#define L2 map[3][1]
#define L3 map[3][0] #define B0 map[2][6]
#define B1 map[2][7]
#define B2 map[3][7]
#define B3 map[3][6] #define D0 map[4][2]
#define D1 map[4][3]
#define D2 map[5][3]
#define D3 map[5][2] const int n = ;
const int m = ;
int deep;
char map[MAXN][MAXN];
char op[MAXL]; bool isValid() {
bool ret;
ret =\
(U0==U1 && U0==U2 && U0==U3) &&\
(L0==L1 && L0==L2 && L0==L3) &&\
(R0==R1 && R0==R2 && R0==R3) &&\
(F0==F1 && F0==F2 && F0==F3) &&\
(B0==B1 && B0==B2 && B0==B3) &&\
(D0==D1 && D0==D2 && D0==D3) ;
return ret;
} void rotateX() {
char ch, ch1, ch2;
// handle right
ch = R0;
R0 = R1;
R1 = R2;
R2 = R3;
R3 = ch; ch1 = F1;
ch2 = F2;
// up -> front
F1 = U1;
F2 = U2;
// back -> up
U1 = B3;
U2 = B0;
// down -> back
B0 = D2;
B3 = D1;
// front -> down
D1 = ch1;
D2 = ch2;
} void rotateY() {
char ch, ch0, ch1; // handle up
ch = U0;
U0 = U1;
U1 = U2;
U2 = U3;
U3 = ch; ch0 = F0;
ch1 = F1;
// left -> front
F0 = L0;
F1 = L1;
// back -> left
L0 = B0;
L1 = B1;
// right -> back
B0 = R0;
B1 = R1;
// front -> right
R0 = ch0;
R1 = ch1;
} void rotateZ() {
char ch, ch2, ch3; // handle front
ch = F0;
F0 = F1;
F1 = F2;
F2 = F3;
F3 = ch; ch2 = U2;
ch3 = U3;
// right -> up
U3 = R0;
U2 = R3;
// down -> right
R0 = D1;
R3 = D0;
// left -> down
D0 = L1;
D1 = L2;
// up -> left
L1 = ch2;
L2 = ch3;
} int getH(){
int cnt = ;
if(map[][] != map[][] || map[][] != map[][]) cnt++;
if(map[][] != map[][] || map[][] != map[][]) cnt++;
if(map[][] != map[][] || map[][] != map[][]) cnt++;
return cnt;
} bool dfs(int d) {
if (d+getH() > deep)
return false;
if (d == deep)
return isValid(); op[d] = 'X';
rotateX();
if (dfs(d+))
return true;
rotateX();
rotateX();
rotateX(); op[d] = 'Y';
rotateY();
if (dfs(d+))
return true;
rotateY();
rotateY();
rotateY(); op[d] = 'Z';
rotateZ();
if (dfs(d+))
return true;
rotateZ();
rotateZ();
rotateZ(); return false;
} int main() {
int i, j, k; #ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif while () {
for (i=; i<n; ++i)
scanf("%s", map[i]);
if (map[][] == '.')
break;
deep = ;
while () {
if (dfs())
break;
++deep;
}
op[deep] = '\0';
puts(op);
} return ;
}

2.4 HDOJ 2691
这题目当时直接拿哈希做的,其实直接转换成longlong兴许还能容易点儿。算法是双广,两种剪枝策略:任何操作的不能与它的逆操作邻接;同一种操作至多进行2次,否则一定可以使用更少操作次数的逆操作实现。这题我使用了找到任何一种魔方的等价态。不使用这个能不能过不清楚。flip函数的就是如何通过正立排列映射为倒立的排列。

 /* 2691 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 typedef long long LL;
typedef unsigned long long ULL; typedef struct {
char a[];
short pre;
short deep; void print() {
rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); rep(i, , ) putchar(a[i]), putchar(' ');
putchar('\n');
rep(i, , ) putchar(a[i]), putchar(' ');
putchar('\n'); rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); rep(i, , ) putchar(' '), putchar(' ');
rep(i, , ) putchar(a[i]), putchar(' ');
rep(i, , ) putchar(' '), putchar(' ');
putchar('\n'); putchar('\n');
}
} node_t; int a[], b[];
int n;
int face[][] = {
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , }
}; int movp[][] = {
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,}
};
int nxt[];
int unxt[];
int ans;
vector<node_t> vc[]; struct Hash {
static const int mod = ;
map<string,int> tb[mod]; void clear() {
rep(i, , mod)
tb[i].clr();
} static int HashCode(const char *s) {
int ret = ; rep(i, , )
ret = (ret * + s[i]) % mod; return ret;
} static LL toLL(const char *s) {
int ret = ;
rep(i, , ) ret = *ret + s[i];
return ret;
} bool find(const char* s) {
int h = HashCode(s);
return tb[h].count(string(s, )) > ;
} bool find(int h, const char *s) {
return tb[h].count(string(s, )) > ;
} int get(const char *s) {
int h = HashCode(s);
return tb[h][string(s, )];
} int get(int h, const char *s) {
return tb[h][string(s, )];
} void update(const char *s, int step) {
int h = HashCode(s);
map<string,int>& tb_ = tb[h];
string ss(s, );
if (tb_.find(ss) == tb_.end())
tb_[ss] = step;
} void update(const char *s, int h, int step) {
map<string,int>& tb_ = tb[h];
string ss(s, );
if (tb_.find(ss) == tb_.end())
tb_[ss] = step;
} }; Hash H[];
void init_pos(); void init() {
init_pos();
} vector<vi> vpos; vi flip(const vi& vtmp) {
vi ret; per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
return ret;
} #define push_vtmp2(a, b) {vtmp.pb(a); vtmp.pb(b);}
#define push_vtmp4(a, b, c, d) {vtmp.pb(a); vtmp.pb(b); vtmp.pb(c); vtmp.pb(d);}
#define push_vtmp6(a, b, c, d, e, f) {vtmp.pb(a); vtmp.pb(b); vtmp.pb(c); vtmp.pb(d); vtmp.pb(e); vtmp.pb(f);}
void init_pos() {
vi vtmp; //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp));
} node_t bnode, enode;
queue<node_t> Q[]; void Init() {
rep(i, , ) {
while (!Q[i].empty()) Q[i].pop();
H[i].clr();
}
} int update(node_t& nd, int idx, int step) {
static char s[]; Hash& h = H[idx];
Hash& hh = H[idx^];
const int sz = SZ(vpos); h.update(nd.a, step);
rep(i, , sz) {
rep(j, , )
s[j] = nd.a[vpos[i][j]];
int hval = Hash::HashCode(s);
if (hh.find(hval, s))
return step + hh.get(hval, s);
} return -;
} int bfs(int idx, int step) {
queue<node_t>& Q = ::Q[idx];
Hash& h = H[idx];
int sz = SZ(Q);
node_t nd, d;
int tmp; while (sz--) {
nd = Q.front();
Q.pop();
rep(i, , ) {
if ((i^) == nd.pre)
continue;
if (i != nd.pre) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ; } else if (nd.deep < ) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ;
} else {
continue;
} if (h.find(d.a)) continue; tmp = update(d, idx, step);
if (tmp >= ) {
return tmp;
} else {
Q.push(d);
}
}
} return -;
} void solve() {
Init(); update(bnode, , );
if (update(enode, , ) >= ) {
puts("");
return ;
}
Q[].push(bnode);
Q[].push(enode); int ans = -, tmp; for (int i=; ;++i) {
tmp = bfs(, i);
if (tmp >= ) {
ans = tmp;
break;
}
tmp = bfs(, i);
if (tmp >= ) {
ans = tmp;
break;
}
} printf("%d\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char s[];
int p[]; {
int l = ;
rep(i, , ) p[l++] = i;
rep(i, , ) p[l++] = i;
p[l++] = ; p[l++] = ;
rep(i, , ) p[l++] = i;
p[l++] = ; p[l++] = ;
rep(i, , ) p[l++] = i;
} init();
scanf("%d", &t);
gets(s);
while (t--) {
int l = ;
rep(j, , ) {
gets(s);
int len = strlen(s);
rep(i, , len) {
if (s[i] == ' ') continue;
bnode.a[p[l++]] = s[i];
}
}
l = ;
rep(j, , ) {
gets(s);
int len = strlen(s);
rep(i, , len) {
if (s[i] == ' ') continue;
enode.a[p[l++]] = s[i];
}
}
bnode.pre = -;
enode.pre = -;
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

2.5 HDOJ 1537 && POJ 1955这道题目杭电上做的人不多,其实就是一道模拟,难在实现3阶魔方的旋转的映射排列。题目大意是给定魔方的状态及一串操作序列,求执行完后最终的魔方状态。
其中counter表示有给定的顺时针旋转,得到互逆的逆时针旋转。

 /* 1537 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; char s[], d[];
int q;
vector<vi> vpos; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate LEFT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate FRONT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate RIGHT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate BACK
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate Top
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate BOTTOM
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
}
} void rotate(int f, int dir) {
int idx = f * ;
if (dir == -) idx += ;
memcpy(d, s, sizeof(d));
vi& p = vpos[idx];
#ifndef ONLINE_JUDGE
assert(idx>= && idx<SZ(p));
#endif
rep(i, , ) s[i] = d[p[i]];
} void printAns(char *s) {
int idx = ; rep(i, , ) {
printf(" ");
rep(j, , ) {
putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
} rep(i, , ) {
rep(j, , ) {
if (j) putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
} rep(i, , ) {
printf(" ");
rep(j, , ) {
putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
}
} void solve() {
int f, d; while (q--) {
scanf("%d%d", &f, &d);
rotate(f, d);
}
printAns(s);
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char op[]; init();
scanf("%d", &t);
rep(tt, , t+) {
rep(i, , ) {
scanf("%s", op);
s[i] = op[];
}
scanf("%d", &q);
printf("Scenario #%d:\n", tt);
solve();
putchar('\n');
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

2.6 HDOJ 2168
写完了上一道题,这道题也基本写完了,重新映射一下输入的三阶魔方以及输出结果。这题就直接过了。注意这道题没有逆时针旋转。题目数据非常弱,完全不用优化。

 /* 2168 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; const int maxl = ;
char ops[maxl];
char s[], d[];
int q;
vector<vi> vpos;
int ipos[], ipos_[]; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate U
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
} // rotate R
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
vpos.pb(vtmp);
} // rotate F
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
vpos.pb(vtmp);
} // rotate D
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
} // rotate L
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
} // rotate B
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
} #ifndef ONLINE_JUDGE
assert(SZ(vpos) == );
memset(ipos, -, sizeof(ipos));
memset(ipos_, -, sizeof(ipos_));
#endif
{
int base; base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[LEFT][i*+j]] = base + j;
}
base += ;
} base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[FRONT][i*+j]] = base + j;
}
base += ;
} base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[BOTTOM][i*+j]] = base + j;
}
base += ;
} base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[BACK][(-i)*+(-j)]] = base + j;
}
base += ;
} base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[TOP][i*+j]] = base + j;
}
base += ;
} base = ;
rep(i, , ) {
rep(j, , ) {
ipos[face[RIGHT][j*+-i]] = base + j;
}
base += ;
} rep(i, , ) {
ipos_[ipos[i]] = i;
}
}
} void rotate(char c1) {
static char uc[] = "GYORWB"; int idx = strchr(uc, c1) - uc; memcpy(d, s, sizeof(d));
rep(j, , )
s[j] = d[vpos[idx][j]];
} void printAns() {
rep(i, , ) d[i] = s[ipos_[i]];
rep(i, , ) {
if (i== || i== || i==) {
putchar(d[i]);
putchar('\n');
} else {
putchar(d[i]);
putchar(' ');
}
}
} void solve() {
int len = strlen(ops); rep(i, , ) s[i] = d[ipos[i]];
rep(i, , len) {
rotate(ops[i]);
} printAns();
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char op[]; init();
scanf("%d", &t);
while (t--) {
rep(i, , ) {
scanf("%s", op);
d[i] = op[];
}
scanf("%s", ops);
solve();
puts("===================================");
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

2.7 HDOJ 2953
这题是个2阶魔方,但是比前面的题目难,难点在于需要对初始魔方进行一个映射。题目是需要是讲魔方复原。但是每个面的颜色存在着不同的组合,这也导致最终魔方的状态不等价。
重新映射后就可以利用预处理的结果了,过预处理的由结束状态魔方执行7步操作可达状态。如果不在预处理状态中,那么bfs找到最优解。

 /* 2953 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 typedef long long LL;
typedef unsigned long long ULL;
typedef struct {
char a[];
int pre, deep;
} node_t; int a[];
char s[];
int face[][] = {
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , }
};
int movp[][] = {
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,,,,,,,,,}
}; ULL HashCode(const char *s) {
ULL ret = ; rep(i, , )
ret = ret * + s[i]; return ret;
} vector<vi> vpos; struct Hash {
map<ULL,int> tb;
map<ULL,int>::iterator iter; void clear() {
tb.clr();
} int find(const char *b) {
const int sz = SZ(vpos);
static char a[]; rep(i, , sz) {
rep(j, , )
a[j] = b[vpos[i][j]];
ULL h = HashCode(a);
iter = tb.find(h);
if (iter != tb.end()) return iter->sec;
} return -;
} bool update(const char *b, int step) {
const int sz = SZ(vpos);
static char a[]; rep(i, , sz) {
rep(j, , )
a[j] = b[vpos[i][j]];
ULL h = HashCode(a);
if (tb.count(h) > ) return true;
} ULL h = HashCode(b);
tb[h] = step;
return false;
}
}; Hash H, HH; vi flip(const vi& vtmp) {
vi ret; per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
per(i, , ) ret.pb(vtmp[i]);
return ret;
} #define push_vtmp2(a, b) {vtmp.pb(a); vtmp.pb(b);}
#define push_vtmp4(a, b, c, d) {vtmp.pb(a); vtmp.pb(b); vtmp.pb(c); vtmp.pb(d);}
#define push_vtmp6(a, b, c, d, e, f) {vtmp.pb(a); vtmp.pb(b); vtmp.pb(c); vtmp.pb(d); vtmp.pb(e); vtmp.pb(f);}
void init_pos() {
vi vtmp; //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); //
vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp)); vtmp.clr();
push_vtmp4(, , , );
push_vtmp6(, , , , , );
push_vtmp6(, , , , , );
push_vtmp4(, , , );
push_vtmp4(, , , );
vpos.pb(vtmp);
vpos.pb(flip(vtmp));
} void init_bfs() {
queue<node_t> Q;
node_t nd, d; rep(i, , )
rep(j, , )
nd.a[face[i][j]] = i;
nd.pre = -;
nd.deep = ;
Q.push(nd); H.update(nd.a, );
for (int step=; step<=; ++step) {
int sz = SZ(Q);
while (sz--) {
nd = Q.front();
Q.pop();
rep(i, , ) {
if ((i^) == nd.pre)
continue;
if (i != nd.pre) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ; } else if (nd.deep < ) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ;
} else {
continue;
} if (!H.update(d.a, step)) {
Q.push(d);
}
}
}
}
} void init() {
init_pos();
init_bfs();
} int bfs() {
int step = ;
queue<node_t> Q;
node_t nd, d; rep(i, , ) nd.a[i] = a[i];
nd.pre = -;
nd.deep = ;
Q.push(nd); HH.update(nd.a, ); while () {
int sz = SZ(Q);
if (sz == ) break;
++step;
while (sz--) {
nd = Q.front();
Q.pop();
rep(i, , ) {
if ((i^) == nd.pre)
continue;
if (i != nd.pre) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ; } else if (nd.deep < ) {
rep(j, , ) d.a[j] = nd.a[movp[i][j]];
d.pre = i;
d.deep = ;
} else {
continue;
} if (!HH.update(d.a, step)) {
int tmp = H.find(d.a);
if (tmp >= ) return step + tmp;
Q.push(d);
}
}
}
} return -;
} void solve() {
static char b[];
rep(j, , ) b[j] = a[j];
int ans = H.find(b); if (ans >= ) {
printf("%d\n", ans);
return ;
} ans = bfs();
printf("%d\n", ans);
} inline int getVal(char c) {
if (c == 'O') return ;
if (c == 'W') return ;
if (c == 'R') return ;
if (c == 'G') return ;
if (c == 'Y') return ;
if (c == 'B') return ;
return -;
} void transfer() {
static int block[][]={
{,,}, {,,}, {,,}, {,,},
{,,}, {,,}, {,,}, {,,}
};
map<char,char> col;
map<char,bool> flag;
col[s[]] = 'B';
flag[s[]] = true;
col[s[]] = 'W';
flag[s[]] = true;
col[s[]] = 'Y';
flag[s[]] = true;
rep(i, , ) {
int cnt = , sum = , has = ;
if(flag[s[block[i][]]]) {
++cnt;
sum += col[s[block[i][]]];
has -= ;
}
if(flag[s[block[i][]]]) {
++cnt;
sum += col[s[block[i][]]];
has -= ;
}
if(flag[s[block[i][]]]){
++cnt;
sum+=col[s[block[i][]]];
has-=;
}
if(cnt != ) continue;
if(sum == 'B'+'W') col[s[block[i][has]]] = 'O';
if(sum == 'B'+'Y') col[s[block[i][has]]] = 'G';
if(sum == 'Y'+'W') col[s[block[i][has]]] = 'R';
}
rep(i, , ) s[i]=col[s[i]];
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char ch;
int p[]; {
#define PUSHP(a, b, c, d) {p[l++]=a;p[l++]=b;p[l++]=c;p[l++]=d;}
int l = ;
PUSHP(, , , );
PUSHP(, , , );
PUSHP(, , , );
PUSHP(, , , );
PUSHP(, , , );
PUSHP(, , , );
} init();
scanf("%d", &t);
rep(tt, , t+) {
rep(i, , ) {
while ((ch=getchar()) <= );
s[i] = ch;
}
transfer();
rep(i, , ) a[p[i]] = getVal(s[i]);
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

2.8 HDOJ 4397
 三阶魔方,增加了X、Y、Z轴的旋转,一道模拟题。大写表示顺时针旋转,小写表示逆时针旋转,判定按照指定序列旋转后魔方能否复原。

 /* 4397 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; char ops[];
char s[], d[];
int q;
vector<vi> vpos; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate U
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate R
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate F
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate D
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate L
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate B
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate X
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[LEFT][], face[FRONT][], face[LEFT][], face[FRONT][], face[LEFT][], face[FRONT][]);
FORCE_MOVE(face[FRONT][], face[RIGHT][], face[FRONT][], face[RIGHT][], face[FRONT][], face[RIGHT][]);
FORCE_MOVE(face[RIGHT][], face[BACK][], face[RIGHT][], face[BACK][], face[RIGHT][], face[BACK][]);
FORCE_MOVE(face[BACK][],face[LEFT][],face[BACK][],face[LEFT][],face[BACK][],face[LEFT][]); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotateY
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]);
FORCE_MOVE(face[BACK][], face[TOP][], face[BACK][], face[TOP][], face[BACK][], face[TOP][]);
FORCE_MOVE(face[BOTTOM][], face[BACK][], face[BOTTOM][], face[BACK][], face[BOTTOM][], face[BACK][]);
FORCE_MOVE(face[FRONT][],face[BOTTOM][],face[FRONT][],face[BOTTOM][],face[FRONT][],face[BOTTOM][]); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotateZ
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]);
FORCE_MOVE(face[LEFT][],face[BOTTOM][],face[LEFT][],face[BOTTOM][],face[LEFT][],face[BOTTOM][]); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
}
} void rotate(char ch) {
static char uc[] = "URFDLBXYZ";
static char lc[] = "urfdlbxyz"; int idx; if (islower(ch)) {
idx = strchr(lc, ch) - lc;
idx = (idx << ) + ; } else {
idx = strchr(uc, ch) - uc;
idx = (idx << );
} #ifndef ONLINE_JUDGE
assert(idx>= && idx<SZ(vpos));
#endif memcpy(d, s, sizeof(d));
rep(j, , )
s[j] = d[vpos[idx][j]];
} void printAns(char *s) {
int idx = ; rep(i, , ) {
printf(" ");
rep(j, , ) {
putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
} rep(i, , ) {
rep(j, , ) {
if (j) putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
} rep(i, , ) {
printf(" ");
rep(j, , ) {
putchar(' ');
putchar(s[idx++]);
}
putchar('\n');
}
} void solve() {
int len = strlen(ops); rep(i, , ) s[i] = i; rep(i, , len) {
rotate(ops[i]);
} bool flag = true;
rep(i, , ) {
if (s[i] != i) {
flag = false;
break;
}
} puts(flag ? "Yes":"No");
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t = ; init();
while (scanf("%s", ops)!=EOF) {
if (t)
putchar('\n');
solve();
++t;
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

2.9 POJ 1297
三阶魔方模拟,利用前面的代码稍微改改可以直接过了。

 /* 1290 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; char s[], d[];
int q;
vector<vi> vpos; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate LEFT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate FRONT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate RIGHT
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate BACK
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate Top
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate BOTTOM
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
}
} void rotate(int x) {
int v = abs(x) - ;
int idx = v * ;
if (x < ) idx += ;
memcpy(d, s, sizeof(d));
vi& p = vpos[idx];
#ifndef ONLINE_JUDGE
assert(idx>= && idx<SZ(p));
#endif
rep(i, , ) s[i] = d[p[i]];
} bool judge() {
rep(i, , ) {
rep(j, , ) {
if (s[face[i][j]] != s[face[i][]])
return false;
}
}
return true;
} void solve() {
int x; while (scanf("%d", &x)!=EOF && x) {
rotate(x);
} bool flag = judge();
puts(flag ? "Yes, grandpa!" : "No, you are wrong!");
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
char op[]; init();
scanf("%d", &t);
rep(tt, , t+) {
rep(i, , ) {
scanf("%s", op);
s[i] = op[];
}
solve();
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

2.10 POJ 3701
三阶魔方搜索,算法还是双广。但是这题wa了好几次,一定要注意读题,首先面1表示FRONT,同样旋转方式都是基于此前提下的,展开方式也是。因此,需要重新映射一下。这个题目不要使用状态等价,可以直接用longlong表示状态,因为$2^{54}$足够了,这里的1的个数一定为9。代码使用G++可以790ms过,C++一直超时。

 /* 3701 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 typedef long long LL;
#define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; char s[], d[];
int one;
vector<vi> movp;
vector<vi> vpos;
map<LL, pair<LL,int> > tb[]; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init_pos();
void init_bfs();
void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate U
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
movp.pb(vtmp);
movp.pb(counter(vtmp));
} // rotate X
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[LEFT][], face[FRONT][], face[LEFT][], face[FRONT][], face[LEFT][], face[FRONT][]);
FORCE_MOVE(face[FRONT][], face[RIGHT][], face[FRONT][], face[RIGHT][], face[FRONT][], face[RIGHT][]);
FORCE_MOVE(face[RIGHT][], face[BACK][], face[RIGHT][], face[BACK][], face[RIGHT][], face[BACK][]);
FORCE_MOVE(face[BACK][],face[LEFT][],face[BACK][],face[LEFT][],face[BACK][],face[LEFT][]); vi vtmp(b, b+);
movp.pb(vtmp);
movp.pb(counter(vtmp));
} // rotate D
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
movp.pb(counter(vtmp));
movp.pb(vtmp);
} // rotate L
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
movp.pb(counter(vtmp));
movp.pb(vtmp);
} // rotateY
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]);
FORCE_MOVE(face[BACK][], face[TOP][], face[BACK][], face[TOP][], face[BACK][], face[TOP][]);
FORCE_MOVE(face[BOTTOM][], face[BACK][], face[BOTTOM][], face[BACK][], face[BOTTOM][], face[BACK][]);
FORCE_MOVE(face[FRONT][],face[BOTTOM][],face[FRONT][],face[BOTTOM][],face[FRONT][],face[BOTTOM][]); vi vtmp(b, b+);
movp.pb(vtmp);
movp.pb(counter(vtmp));
} // rotate R
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
movp.pb(vtmp);
movp.pb(counter(vtmp));
} // rotate B
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
movp.pb(vtmp);
movp.pb(counter(vtmp));
} // rotateZ
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]);
FORCE_MOVE(face[LEFT][],face[BOTTOM][],face[LEFT][],face[BOTTOM][],face[LEFT][],face[BOTTOM][]); vi vtmp(b, b+);
movp.pb(counter(vtmp));
movp.pb(vtmp);
} // rotate F
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
movp.pb(counter(vtmp));
movp.pb(vtmp);
}
} bool judge(char *s) {
int c = ;
rep(j, , )
c += s[face[FRONT][j]] - ''; return c == one;
} inline LL zip(char *s) {
LL ret = ; rep(i, , ) {
if (s[i] == '')
ret |= 1LL << i;
} return ret;
} inline void unzip(char *s, LL val) {
rep(i, , ) {
if (val & (1LL<<i))
s[i] = '';
else
s[i] = '';
}
} struct node_t {
LL st;
int pre;
int dep; node_t() {}
node_t(LL st, int pre, int dep):
st(st), pre(pre), dep(dep) {} void print() {
char sa[];
unzip(sa, st); int idx = ; printf("op = %d:\n", pre+);
rep(i, , ) {
printf(" ");
rep(j, , ) putchar(sa[idx++]);
putchar('\n');
} rep(i, , ) {
rep(j, , ) putchar(sa[idx++]);
putchar('\n');
} rep(i, , ) {
printf(" ");
rep(j, , ) putchar(sa[idx++]);
putchar('\n');
}
putchar('\n');
}
}; inline bool Visit(LL st, int idx) {
return tb[idx].count(st) > ;
} queue<node_t> Q[]; LL bfs(int idx) {
queue<node_t>& Q = ::Q[idx];
map<LL, pair<LL,int> >& tb = ::tb[idx];
const int sz = SZ(movp);
int szQ = SZ(Q);
node_t nd, d;
static char sa[], sb[]; while (szQ--) {
nd = Q.front();
Q.pop();
unzip(sa, nd.st);
rep(i, , sz) {
if ((i^) == nd.pre) continue;
if (i==nd.pre && nd.dep>=) continue; rep(j, , ) sb[j] = sa[movp[i][j]];
d.st = zip(sb);
if (i != nd.pre) {
d.dep = ;
d.pre = i;
} else {
d.dep++;
} if (Visit(d.st, idx)) continue;
tb[d.st] = mp(nd.st, i);
if (Visit(d.st, idx^)) return d.st; Q.push(d);
}
break;
} return -;
} void solve() {
int& c = one; c = ;
rep(i, , ) {
c += s[i] - '';
} if (judge(s)) {
puts("yes");
puts("");
puts("");
return ;
} LL bst = zip(s);
Q[].push(node_t(bst, -, -));
tb[][bst] = mp(-, -); memset(s, '', sizeof(s));
rep(j, , ) s[face[FRONT][j]] = '';
LL est = zip(s);
Q[].push(node_t(est, -, -));
tb[][est] = mp(-, -); LL st = -;
int t = ;
while (!Q[].empty() || !Q[].empty()) {
if (t-- == ) break;
if (!Q[].empty()) {
st = bfs();
if (st >= ) break;
}
if (!Q[].empty()) {
st = bfs();
if (st >= ) break;
}
} if (st == -) {
puts("no");
return ;
} LL st1 = st;
LL st2 = st;
vi ans1, ans2; pair<LL,int> p;
while (st1 != -) {
p = tb[][st1];
if (p.fir == -) break;
ans1.pb(p.sec);
st1 = p.fir;
}
while (st2 != -) {
p = tb[][st2];
if (p.fir == -) break;
ans2.pb(p.sec);
st2 = p.fir;
} printf("yes\n%d\n", SZ(ans1)+SZ(ans2));
per(i, , SZ(ans1)) {
printf("%d\n", ans1[i]+);
}
rep(i, , SZ(ans2)) {
printf("%d\n", (ans2[i]^)+);
} // rep(i, 0, 2) {
// tb[i].clr();
// while (!Q[i].empty()) Q[i].pop();
// }
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif char ss[];
int p[] = {
, , ,
, , ,
, , ,
, , , , , , , , , , , ,
, , , , , , , , , , , ,
, , , , , , , , , , , ,
, , ,
, , ,
, ,
}; init();
int idx = ;
rep(i, , ) {
gets(ss);
int len = strlen(ss);
rep(i, , len) {
if (ss[i]=='' || ss[i]=='')
s[p[idx++]] = ss[i];
}
}
assert(idx == );
solve(); #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

2.11 SPOJ IOPC1201
还是一个三阶魔方,给定一个操作序列,问最少执行多少次这个操作序列可以回到最初状态。题目看起来很来,实际很简单。一个操作序列其实就是从初始状态$p$到状态$q$的映射关系,可以将这个排列映射看成图,比如0->1->2->3->0。那么只要找到排列中的所有的环及其长度,这些长度的最小公倍数就是最优解了。这题挺简单的,做的人好少。

 /* SPOJ */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 inline int lcm(int a, int b) {
int g = __gcd(a, b);
return a/g*b;
} #define LEFT 0
#define FRONT 1
#define RIGHT 2
#define BACK 3
#define TOP 4
#define BOTTOM 5
int face[][] = {
/*Left*/ {, , , , , , , , },
/*Front*/ {, , , , , , , , },
/*Right*/ {, , , , , , , , },
/*Back*/ {, , , , , , , , },
/*Top*/ {, , , , , , , , },
/*Bottom*/ {, , , , , , , , }
}; const int maxl = ;
char ops[maxl];
char s[], d[];
int q;
vector<vi> vpos; vi counter(const vi& p) {
int a[], b[]; rep(i, , ) a[i] = i;
rep(i, , ) {
rep(j, , ) b[j] = a[p[j]];
memcpy(a, b, sizeof(b));
} return vi(a, a+);
} void init() {
int a[], b[]; #define MOVE_ROW(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_ROW_(des, src)\
{\
rep(i, , )\
b[face[des][i]] = a[face[src][i]];\
} #define MOVE_COL(des, src)\
{\
rep(i, , )\
b[face[des][i*]] = a[face[src][i*]];\
}
#define FORCE_MOVE(da, sa, db, sb, dc, sc)\
{\
b[da] = a[sa];\
b[db] = a[sb];\
b[dc] = a[sc];\
} // rotate U
{ rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[TOP];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW(LEFT, FRONT);
MOVE_ROW(FRONT, RIGHT);
MOVE_ROW(RIGHT, BACK);
MOVE_ROW(BACK, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate R
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[RIGHT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[FRONT][], face[TOP][], face[FRONT][], face[TOP][], face[FRONT][]); // MOVE_COL(TOP, FRONT);
FORCE_MOVE(face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][], face[FRONT][], face[BOTTOM][]); // MOVE_COL(FRONT, BOTTOM);
FORCE_MOVE(face[BOTTOM][], , face[BOTTOM][], , face[BOTTOM][], ); // MOVE_COL(BOTTOM, BACK);
FORCE_MOVE(, , , , , ); // MOVE_COL(BACK, TOP); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate F
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[FRONT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][]); // MOVE_COL(TOP, LEFT);
FORCE_MOVE(face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][]); // MOVE_COL(RIGHT, TOP);
FORCE_MOVE(face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][], face[BOTTOM][], face[RIGHT][]); // MOVE_COL(BOTTOM, RIGHT);
FORCE_MOVE(face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][], face[LEFT][], face[BOTTOM][]); // MOVE_COL(LEFT, BOTTOM); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate D
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BOTTOM];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_ROW_(FRONT, LEFT);
MOVE_ROW_(RIGHT, FRONT);
MOVE_ROW_(BACK, RIGHT);
MOVE_ROW_(LEFT, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate L
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[LEFT];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
MOVE_COL(FRONT, TOP);
MOVE_COL(BOTTOM, FRONT);
FORCE_MOVE(, , , , , ); //MOVE_COL(BACK, BOTTOM);
FORCE_MOVE(, , , , , ); // MOVE_COL(TOP, BACK); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
} // rotate B
{
rep(i, , ) a[i] = i; memcpy(b, a, sizeof(a));
int* mf = face[BACK];
rep(i, , ) {
rep(j, , ) {
b[mf[i*+j]] = a[mf[(-j)*+i]];
}
}
FORCE_MOVE(face[LEFT][], face[TOP][], face[LEFT][], face[TOP][], face[LEFT][], face[TOP][]); // MOVE(LEFT, TOP);
FORCE_MOVE(face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][], face[TOP][], face[RIGHT][]); // MOVE(TOP, RIGHT);
FORCE_MOVE(face[RIGHT][], , face[RIGHT][], , face[RIGHT][], ); // MOVE(RIGHT, BOTTOM);
FORCE_MOVE(, face[LEFT][], , face[LEFT][], , face[LEFT][]); // MOVE(BOTTOM, LEFT); vi vtmp(b, b+);
vpos.pb(vtmp);
vpos.pb(counter(vtmp));
}
} void rotate(char c1, char c2='\0') {
static char uc[] = "URFDLB"; int idx = strchr(uc, c1) - uc, n = ;
idx <<= ;
if (c2 == '') {
n++;
} else if (c2 == '\'') {
idx += ;
} #ifndef ONLINE_JUDGE
assert(idx>= && idx<SZ(vpos));
#endif rep(i, , n) {
memcpy(d, s, sizeof(d));
rep(j, , )
s[j] = d[vpos[idx][j]];
}
} bool visit[];
void solve() {
int len = strlen(ops);
int i = ;
char c1, c2; rep(i, , ) s[i] = i;
while (i < len) {
c1 = ops[i];
if (ops[i+]=='\'' || ops[i+]=='') {
c2 = ops[i+];
++i;
} else {
c2 = '\0';
}
rotate(c1, c2);
++i;
} memset(visit, false, sizeof(visit));
int ans = ;
memcpy(d, s, sizeof(s)); rep(i, , ) {
if (visit[i]) continue;
int c = ;
visit[i] = true; int v = s[i];
while (v != i) {
visit[v] = true;
++c;
v = s[v];
} ans = lcm(ans, c);
} printf("%d\n", ans);
} int main() {
cin.tie();
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t; init();
scanf("%d", &t);
while (t--) {
scanf("%s", ops);
solve();
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

3. 总结
rubik魔方问题主要涉及IDA*,双广,哈希等算法,算是比较基本,但是实现起来稍微麻烦的问题。因为这类问题做的人不多,单独拎出来做个系列。下个系列打算做crossword。当年携程比赛就是几道难易程度不等的crossword,还是蛮有趣的。

【ACM】魔方十一题的更多相关文章

  1. 经典算法题每日演练——第十一题 Bitmap算法

    原文:经典算法题每日演练--第十一题 Bitmap算法 在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场 ...

  2. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++85——完美数

    本题是浙江理工大学ACM入队200题第八套中的L题 我们先来看一下这题的题面. 题面 题目描述 任何一个自然数的约数中都有1和它本身,我们把小于它本身的因数叫做这个自然数的真约数. 如6的所有真约数是 ...

  3. 「浙江理工大学ACM入队200题系列」问题 K: 零基础学C/C++84——奇偶ASCII值判断

    本题是浙江理工大学ACM入队200题第八套中的K题 我们先来看一下这题的题面. 题面 题目描述 任意输入一个字符,判断其ASCII是否是奇数,若是,输出YES,否则,输出NO; 例如,字符A的ASCI ...

  4. 「浙江理工大学ACM入队200题系列」问题 J: 零基础学C/C++83——宁宁的奥数路

    本题是浙江理工大学ACM入队200题第八套中的J题 我们先来看一下这题的题面. 题面 题目描述 宁宁参加奥数班,他遇到的第一个问题是这样的:口口口+口口口=口口口,宁宁需要将1~9 九个数分别填进对应 ...

  5. 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积

    本题是浙江理工大学ACM入队200题第八套中的E题 我们先来看一下这题的题面. 题面 输入 输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据一共有n个,接着是n个整数,你 ...

  6. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++52——计算数列和2/1,3/2,5/3,8/5......

    本题是浙江理工大学ACM入队200题第五套中的L题 我们先来看一下这题的题面. 题面 题目描述 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13,-- 计算这个数列的前n项和.注意: ...

  7. 「浙江理工大学ACM入队200题系列」问题 F: 零基础学C/C++39——求方程的解

    本题是浙江理工大学ACM入队200题第四套中的F题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  8. 「浙江理工大学ACM入队200题系列」问题 A: 零基础学C/C++34—— 3个数比较大小(冒泡排序与选择排序算法)

    本题是浙江理工大学ACM入队200题第四套中的A题,同时给出了冒泡排序和选择排序算法 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习 ...

  9. 「浙江理工大学ACM入队200题系列」问题 H: 零基础学C/C++18——三位数反转

    本题是浙江理工大学ACM入队200题第二套中的H题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

随机推荐

  1. 制作一个可以给team所有成员用的开发者证书

    1. 将证书的private key导出一个.p12的文件给别人 2. 从apple developer网站下载证书对应的provisioning profile 待优化

  2. js中常用数组方法concat join push pop slice splice shift

    javascript给我们很多常用的 数组方法,极大方便了我们做程序.下面我们来介绍下常用的集中数组方法. 比如 concat() join() push() pop() unshift() shif ...

  3. HTML页面处理以及资源文件的加载

    Javascript 异步加载详解 这篇文章很详细的介绍了HTML的页面处理以及资源文件的加载. 本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading ...

  4. 全栈式JavaScript

    如今,在创建一个Web应用的过程中,你需要做出许多架构方面的决策.当然,你会希望做的每一个决定都是正确的:你想要使用能够快速开发的技术,支持持续的迭代,最高的工作效率,迅速,健壮性强.你想要精益求精并 ...

  5. rpc 小例子

    RpcFramework /* * Copyright 2011 Alibaba.com All right reserved. This software is the * confidential ...

  6. Maven在项目中的应用

    http://192.168.0.253:8081/nexus/#view-repositories;thirdparty~uploadPanel 使用局域网搭建的环境,输入用户名和密码登录,上传ja ...

  7. mapred和mapreduce

    总体上看,Hadoop MapReduce分为两部分:一部分是org.apache.hadoop.mapred.*,这里面主要包含旧的API接口以及MapReduce各个服务(JobTracker以及 ...

  8. MariaDB Galera Cluster集群

    一.MariaDB Galera Cluster概要: 1.简述: MariaDB Galera Cluster 是一套在mysql innodb存储引擎上面实现multi-master及数据实时同步 ...

  9. Javascript与Flash通信全解析

    原文:https://www.imququ.com/post/39.html Flash已经提供了ExternalInterface接口与JavaScript通信,ExternalInterface有 ...

  10. HDU 4639 Hehe(字符串处理,斐波纳契数列,找规律)

    题目 //每次for循环的时候总是会忘记最后一段,真是白痴.... //连续的he的个数 种数 //0 1 //1 1 //2 2 //3 3 //4 5 //5 8 //…… …… //斐波纳契数列 ...