0w1

IOI'94 The Clocks ( Binary Enumeration )

PEG Judge - IOI '94 - The Clocks
一開始想用 PFS,後來想一想沒有權重可以直接BFS,寫完丟出去才發現 RE / TLE。。

// Will TLE O( ( ans.size() ) ! )
#include <bits/stdc++.h>
using namespace std;

struct State{
    int clk[ 9 ];
    State(){}
    void read(){
        for(int i = 0; i < 9; ++i){
            int t; scanf("%d", &t);
            t /= 3;
            t %= 4; // t: [ 0, 3 ]
            clk[ i ] = t;
        }
    }
    void clk90(int id){
        clk[ id ] = ( clk[ id ] + 1 ) % 4;
    }
    void dial(int op){
        if( op == 1 )
            clk90( 0 ), clk90( 1 ), clk90( 3 ), clk90( 4 );
        if( op == 2 )
            clk90( 0 ), clk90( 1 ), clk90( 2 );
        if( op == 3 )
            clk90( 1 ), clk90( 2 ), clk90( 4 ), clk90( 5 );
        if( op == 4 )
            clk90( 0 ), clk90( 3 ), clk90( 6 );
        if( op == 5 )
            clk90( 1 ), clk90( 3 ), clk90( 4 ), clk90( 5 ), clk90( 7 );
        if( op == 6 )
            clk90( 2 ), clk90( 5 ), clk90( 8 );
        if( op == 7 )
            clk90( 3 ), clk90( 4 ), clk90( 6 ), clk90( 7 );
        if( op == 8 )
            clk90( 6 ), clk90( 7 ), clk90( 8 );
        if( op == 9 )
            clk90( 4 ), clk90( 5 ), clk90( 7 ), clk90( 8 );
    }
    bool done(){
        for(int i = 0; i < 9; ++i)
            if( clk[ i ] )
                return false;
        return true;
    }
    bool operator < (const State &oth) const{
        for(int i = 0; i < 9; ++i){
            if( clk[ i ] != oth.clk[ i ] )
                return clk[ i ] < oth.clk[ i ];
            return true;
        }
    }
    void print(){
        for(int i = 0; i < 9; ++i)
            printf("%d%c", clk[ i ], i == 8 ? '\n' : ' ');
    }
} s0;

struct Seq{
    vector<int> vec;
    Seq(){ vec.clear(); }
    void print(){
        for(int i = 0; i < vec.size(); ++i)
            printf("%d%c", vec[ i ], i == vec.size() - 1 ? '\n' : ' ');
    }
};

struct SeqState{
    Seq seq;
    State state;
    SeqState(){}
    SeqState(Seq _seq, State _state): seq( _seq ), state( _state ){}
};

void solve(){
    queue< SeqState > que;
    que.push( SeqState( Seq(), s0 ) );
    set< State > vis;
    vis.insert( s0 );
    while( !que.empty() ){
        Seq seq = que.front().seq;
        State state = que.front().state;
        que.pop();
        state.print();
        if( state.done() ){
            seq.print();
            return;
        }
        for(int i = 1; i <= 9; ++i){
            State ns; // memcpy( &ns, &state, sizeof(ns) );
            ns = state;
            ns.dial( i );
            if( vis.count( ns ) ) continue;
            vis.insert( ns );
            Seq nseq; // memcpy( &nseq, &seq, sizeof(nseq) );
            nseq = seq;
            nseq.vec.push_back( i );
            que.push( SeqState( nseq, ns ) );
        }
    }
}

int main(){
    s0.read();
    solve();
    return 0;
}

因為事實上這個操作序列是可以長達 20以上的,例如
input:
12 12 12 12 12 12 12 12 9
output:
2 2 3 3 3 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9
而這種無腦搜索考慮了排列,所以階層級的 20! > 1e18真是天文數字,而且還沒 TLE就已經 MLE了。注意到這些操作之間是不會相互影響的且順序是沒有差別的,因此事實上會導致不同結果的操作數只有 4 ^ 9種,每個盤面都只能選擇 不轉、90、180、270度其中一個。為了方便枚舉,我將每個盤面用 2個位元表示,所以 9個盤面用 18個位元表示。枚舉所有狀態並嘗試,如果符合要求就更新答案。

#include <bits/stdc++.h>
using namespace std;

struct State{
    int clk[ 9 ];
    State(){}
    void read(){
        for(int i = 0; i < 9; ++i){
            int t; scanf("%d", &t);
            t /= 3;
            t %= 4; // t: [ 0, 3 ]
            clk[ i ] = t;
        }
    }
    void clk90(int id){
        clk[ id ] = ( clk[ id ] + 1 ) % 4;
    }
    void dial(int op){
        if( op == 1 )
            clk90( 0 ), clk90( 1 ), clk90( 3 ), clk90( 4 );
        if( op == 2 )
            clk90( 0 ), clk90( 1 ), clk90( 2 );
        if( op == 3 )
            clk90( 1 ), clk90( 2 ), clk90( 4 ), clk90( 5 );
        if( op == 4 )
            clk90( 0 ), clk90( 3 ), clk90( 6 );
        if( op == 5 )
            clk90( 1 ), clk90( 3 ), clk90( 4 ), clk90( 5 ), clk90( 7 );
        if( op == 6 )
            clk90( 2 ), clk90( 5 ), clk90( 8 );
        if( op == 7 )
            clk90( 3 ), clk90( 4 ), clk90( 6 ), clk90( 7 );
        if( op == 8 )
            clk90( 6 ), clk90( 7 ), clk90( 8 );
        if( op == 9 )
            clk90( 4 ), clk90( 5 ), clk90( 7 ), clk90( 8 );
    }
    bool done(){
        for(int i = 0; i < 9; ++i)
            if( clk[ i ] )
                return false;
        return true;
    }
    void print(){
        for(int i = 0; i < 9; ++i)
            printf("%d%c", clk[ i ], i == 8 ? '\n' : ' ');
    }
} s0;

struct Seq{
    vector<int> vec;
    Seq(){ vec.clear(); }
    bool operator < (const Seq &oth) const{
        if( vec.size() != oth.vec.size() )
            return vec.size() < oth.vec.size();
        for(int i = 0; i < vec.size(); ++i)
            if( vec[ i ] != oth.vec[ i ] )
                return vec[ i ] < oth.vec[ i ];
        return true;
    }
    void print(){
        for(int i = 0; i < vec.size(); ++i)
            printf("%d%c", vec[ i ], i == vec.size() - 1 ? '\n' : ' ');
    }
};

void solve(){
    assert( !s0.done() );
    Seq ans;
    for(int S = 1; S < ( 1 << 18 ); ++S){
        State z = s0;
        Seq seq;
        for(int i = 0; i < 9; ++i){
            int t = ( S >> ( i * 2 ) ) % 4;
            for(int j = 0; j < t; ++j){
                z.dial( i + 1 );
                seq.vec.push_back( i + 1 );
            }
        }
        if( z.done() ){
            if( ans.vec.empty() || seq < ans )
                ans = seq;
        }
    }
    ans.print();
}

int main(){
    s0.read();
    solve();
    return 0;
}