1. 程式人生 > >gym 100520 C. Catalian Sequences

gym 100520 C. Catalian Sequences

bfs打表,狀態數有點多,需要剔除掉無用的狀態才不會t。

i——當前序列長度

A——題目中所給,相鄰的兩個數ai+1 > ai的個數

low——下次新增數最低從哪個開始

s——用了哪些數

last——上一個以哪個數結尾。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MX = 2e4+7;
ll ret[33];
struct node{
    int i,A,low,last;
    ll s;
    node(){}
    node(int i, int A, int low, ll s, int last) : i(i), A(A), low(low), s(s), last(last){}
    bool operator < (const node &t) const{
        if(i != t.i) return i < t.i;
        if(A != t.A) return A < t.A;
        if(low != t.low) return low < t.low;
        if(s != t.s) return s < t.s;
        return last < t.last;
    }
    //去掉多餘的狀態,
    void get_s()
    {
        ll t = (1<<low) - 1;
        s -= (s&t);
    }
};


inline int get_low(ll s, int k, int low)
{
    s &= (1<<k)-1;
    for(int i = k-1; i >= low; --i)
        if((s>>i)&1) return i;
    return low;
}

void init()
{
    ret[1] = 1;
    queue<node> que;
    map<node,ll> ans;
    //0 0
    node u = node(2,0,0,1,0);
    que.push(u); ans[u] = 1;
    //0 1
    u = node(2,1,0,3,1);
    que.push(u); ans[u] = 1;
    while(que.size()) {
        node u = que.front(); que.pop();
        ret[u.i] += ans[u];
        if(u.i >= 32) continue;
        node v;
        for(int k = u.low; k <= u.A+1; k++) {
            int tmpA = (k > u.last? u.A+1 : u.A);
            v = node(u.i+1, tmpA, get_low(u.s,k,u.low), u.s|(1<<k), k);
            v.get_s();
            if(!ans.count(v)) {
                que.push(v);
                ans[v] = ans[u];
            }
            else ans[v] += ans[u];
        }
    }
}

int main()
{
#ifdef LOCAL
    //freopen("input.txt","r",stdin);
#else
    freopen("catalian.in","r",stdin);
    freopen("catalian.out","w",stdout);
#endif // LOCAL
    init();
    int n,cas = 0;
    while(~scanf("%d",&n) && n){
        printf("Case #%d: %lld\n",++cas,ret[n]);
    }
    return 0;
}