2022.3.16
阿新 • • 發佈:2022-03-16
藍書
AcWing 181. 迴轉遊戲
思路:一開始先得把表給打好,就是每個數字對應的位置找到,到時候換位置的時候就很方便不用一個個打。我們的目的是把中間八個格子變成一樣的,對於中間八個裡的某一個數,變成一樣的次數為8-該數的個數。把它當成估計函式,如果當前的操作次數加上估計函式已經超過了限定的次數就退出。當需要的次數為0的時候說明已經成功了。還需要剪枝,噹噹前操作是上一個操作的反操作的時候就剪,因為這樣做等於又恢復原狀了,等於沒變。
打表看了程式碼,其他沒看自己寫。vector和char陣列比很慢。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=30+10,INF=1e8; int db[10][10] = { {0, 2, 6, 11, 15, 20, 22}, {1, 3, 8, 12, 17, 21, 23}, {10, 9, 8, 7, 6, 5, 4}, {19, 18, 17, 16, 15, 14, 13}, {23, 21, 17, 12, 8, 3, 1}, {22, 20, 15, 11, 6, 2, 0}, {13, 14, 15, 16, 17, 18, 19}, {4, 5, 6, 7, 8, 9, 10}, }; int fop[10] = {5, 4, 7, 6, 1, 0, 3, 2}; int cen[10] = {6, 7, 8, 11, 12, 15, 16, 17}; int a[N]; vector<char> ans; int check() { int ans = 0; int sum[5] = {0}; for (int i = 0; i < 8;i++) { sum[a[cen[i]]]++; } for (int i = 1;i<=3;i++) { ans = max(ans, sum[i]); } return 8 - ans; } void change(int op) { int x = a[db[op][0]]; for (int i = 0; i < 6;i++) a[db[op][i]] = a[db[op][i + 1]]; a[db[op][6]] = x; } bool dfs(int dep,int tot,int last) { if(check()+tot>dep) return 0; if(check()==0) return 1; for (int i = 0; i < 8;i++) { if(i==last) continue; change(i); ans.push_back('A' + i); if(dfs(dep,tot+1,fop[i])) return 1; ans.pop_back(); change(fop[i]); } return 0; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; while(cin>>n) { if(n==0) break; a[0] = n; for (int i = 1; i < 24;i++) { cin >> a[i]; } int dep = 0; while(!dfs(dep,check(),-1)) dep++; if(dep) { for(auto x:ans) cout << x; cout <<'\n'<<a[8]<<'\n'; } else cout << "No moves needed"<<'\n'<<a[8]<<'\n'; while(ans.size()) ans.pop_back(); } return 0; }