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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值