1. 程式人生 > 其它 >2022.3.16

2022.3.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;
}