0. 前言
打了两年的百度之星,都没进决赛。我最大的感受就是还是太弱,总结起来就是:人弱就要多做题,人傻就要多做题。
题目还是按照分类做可能效果比较好,因此,就有了做几个系列的计划。这是系列中的第一个,解决OJ中有关魔方的问题。
1. 概述
魔方大概会涉及两类算法:搜索和模拟。这里的搜索方式一般是双广或者bfs+剪枝,因为双广基本上就可以把题目都解了,所以我也没去
考虑A*。我自身不会玩儿魔方,因此剪枝策略也就两种,不过效果还是很好的。模拟就相对简单,仅需要了解几种旋转的方式基本上是可解。
搜索过程中存在状态爆照问题,因为对于同一个魔方从不同的角度观察得到的抽象数据类型可能不尽相同,但是状态却等价。因此,
很多题需要找到所有可能等价的状态,这其实也是一堆排列。
写魔方旋转以及等价状态,我没有什么特别好的办法。不过由给定的顺时针,可以得到相应的逆时针;由正立状态及倒立状态的映射关系,可以
仅仅通过描述正立排列迅速得到倒立状态。
魔方问题的关键就在于剪枝,双广别写萎了,以及状态等价。
2. 题目
2.1 HDOJ 4801
这是一道2阶魔方,前面做过题解,请参考【HDOJ】4801 Pocket Cube 的几种解法和优化。
2.2 HDOJ 5292
题目大意是给定任何的2阶魔方,需要判定该魔方能否复原。因为这个题目的case范围是$10^4$,所以直接在网上找的结论。具体缘由不清楚。
1 /* 5292 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 #pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 int a[11][11]={ 45 0,0,0,0,1,0,-1,0,0,0,0, 46 0,0,0,0,-1,0,1,0,0,0,0, 47 -1,0,1,0,0,0,0,0,-1,0,1, 48 1,0,-1,0,0,0,0,0,1,0,-1, 49 0,0,0,0,1,0,-1,0,0,0,0, 50 0,0,0,0,-1,0,1,0,0,0,0, 51 0,0,0,0,0,0,0,0,0,0,0, 52 0,0,0,0,0,0,0,0,0,0,0, 53 }; 54 55 int main() { 56 ios::sync_with_stdio(false); 57 #ifndef ONLINE_JUDGE 58 freopen("data.in", "r", stdin); 59 freopen("data.out", "w", stdout); 60 #endif 61 62 int t; 63 char op[16]; 64 65 scanf("%d", &t); 66 rep(tt, 1, t+1) { 67 getchar(); 68 int sum = 0; 69 rep(i, 0, 8) { 70 gets(op); 71 int len = strlen(op); 72 #ifndef ONLINE_JUDGE 73 puts(op); 74 #endif 75 rep(j, 0, len) { 76 if (op[j]=='y' || op[j]=='w') 77 sum += a[i][j]; 78 } 79 } 80 printf("Case #%d: ", tt); 81 puts(sum%3==0 ? "YES":"NO"); 82 } 83 84 #ifndef ONLINE_JUDGE 85 printf("time = %d.\n", (int)clock()); 86 #endif 87 88 return 0; 89 }