Pocket Cube (模擬+DFS)
阿新 • • 發佈:2019-01-04
題意:給一個n,按下圖順序輸入,求n次操作能轉出最多多少個面.
題解:dfs模擬即可,不過需要剪枝,不然爆炸~//二階魔方模板,三階同理
程式碼如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; typedef long long LL; #define lson id<<1 #define rson id<<1|1 const int maxn = 10; const int inf = 0x3f3f3f3f; //二階魔方 int mp[30], s[10][30], n;//mp[]為中間變數,s[x][]儲存的是dfs第x層的mp[] int turn[6][30] = { { 0,2,6,12,16,18,20,22,4,5,11,10 },//0~7為轉的那一圈,8~11為與之相對的側面的一面也要轉同向(請摺紙做!!!) { 1,3,7,13,17,19,21,23,9,8,14,15 }, { 1,0,4,10,18,19,15,9,23,22,20,21 }, { 3,2,5,11,16,17,14,8,7,6,12,13 }, { 4,5,6,7,8,9,23,22,0,2,3,1 }, { 10,11,12,13,14,15,21,20,16,17,19,18 } }; //剪枝三:同一flag操作>=3就沒有意義了 int cnt[10][10];//用於記錄第x層的flag操作次數 int z_cnt[10];//同mp與s的關係 int cas = 1;//用於輸出所有中間結果的 void debug() { cout << endl; cout << "Case " << cas++ << endl; cout << " " << mp[0] << " " << mp[1] << endl; cout << " " << mp[2] << " " << mp[3] << endl; for (int i = 4; i <= 9; i++) cout << mp[i] << " "; cout << endl; for (int i = 10; i <= 15; i++) cout << mp[i] << " "; cout << endl; cout << " " << mp[16] << " " << mp[17] << endl; cout << " " << mp[18] << " " << mp[19] << endl; cout << " " << mp[20] << " " << mp[21] << endl; cout << " " << mp[22] << " " << mp[23] << endl; } int check() { int cnt = 0; int t = mp[0]; if (t == mp[1] && t == mp[2] && t == mp[3])cnt++; t = mp[4]; if (t == mp[5] && t == mp[10] && t == mp[11])cnt++; t = mp[6]; if (t == mp[7] && t == mp[12] && t == mp[13])cnt++; t = mp[8]; if (t == mp[9] && t == mp[14] && t == mp[15])cnt++; t = mp[16]; if (t == mp[17] && t == mp[18] && t == mp[19])cnt++; t = mp[20]; if (t == mp[21] && t == mp[22] && t == mp[23])cnt++; //debug(); //cout << "cnt== " << cnt << endl; return cnt; } void turning(int flag) { int x, y, z; x = mp[turn[flag][0]], y = mp[turn[flag][1]]; for (int i = 0; i < 6; i++) mp[turn[flag][i]] = mp[turn[flag][i + 2]]; mp[turn[flag][6]] = x, mp[turn[flag][7]] = y; z = mp[turn[flag][8]]; for (int i = 8; i < 11; i++) mp[turn[flag][i]] = mp[turn[flag][i + 1]]; mp[turn[flag][11]] = z; } void init(int x)//x為層數 { for (int i = 0; i < 25; i++) mp[i] = s[x][i]; for (int i = 0; i < 6; i++) z_cnt[i] = cnt[x][i]; } int dfs(int flag, int x) //flag為轉的型別,x為層數 { turning(flag); int y = check(); if (x == n) return y; if (y == 6) return y; //剪枝二:當有一組出現6時可以結束了 //先將當前層的mp存下來 for (int i = 0; i < 25; i++) s[x][i] = mp[i]; for (int i = 0; i < 6; i++) cnt[x][i] = z_cnt[i]; x++; for (int i = 0; i < 6; i++) { int j = flag ^ i; if ((flag^i) == 1) continue;//剪枝一:左上一次,右上一次就復原了,剪調 z_cnt[i]++; if (z_cnt[i] >= 3) continue;//剪枝三 init(x - 1); y = max(y, dfs(i, x)); } return y; } void solve() { init(0); memset(cnt, 0, sizeof(cnt)); int ans = check(); for (int i = 0; i < 6; i++) { init(0); z_cnt[i]++; ans = max(ans, dfs(i, 1)); } cout << ans << endl; } void read() { for (int i = 0; i < 24; i++) scanf("%d", &s[0][i]); } int main() { while (~scanf("%d", &n)) { read(); solve(); } return 0; }