$[POJ1187]$ 陨石的秘密 题解

\(POJ1187\)

真是一个有趣的题目……我真是……唉……

我相信肯定有很多人拿到这道题会设如下的状态:

\(f[l1][l2][l3][d]\)为有\(l1\)\(\{ \}\)\(l2\)\([]\)\(l3\)\(()\)时深度为\(d\)的个数,但是你想一下就会发现,不能转移!

因为你无法控制子状态中\(d\)的最大值,可怜~(@谁是鸽王)

于是就有这样一种神仙状态:\(f[l1][l2][l3][d]\)为有\(l1\)\(\{ \}\),\(l2\)\([]\)\(l3\)\(()\)时深度不超过\(d\)的个数!

\(Woc\),太妙了吧,这样我们就不用考虑最大值,只用用排列组合将子状态弄一起就行了!

具体转移:

考虑我们的当前串为两个部分,那么我们算出两个部分的答案后相乘即可,至于每个部分,我们枚举外面\(\{ \}\)\([]\),()的个数即可,这里要注意一下循环顺序,其他的问题就不大了。

上代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
inline int read()
{
    int f=1,w=0;char x=0;
    while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
    while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
    return w*f;
}
const int p=11380;
int L1,L2,L3,D,f[20][20][30][40];
inline int Dfs(int l1,int l2,int l3,int d)
{
    int ans=0;
    if(!d&&(l1|l2|l3)) return 0;
    if(!(l1|l2|l3)) return f[l1][l2][l3][d]=1;
    if(f[l1][l2][l3][d]) return f[l1][l2][l3][d];
    for(int i=0;i<=l3;i++)
    {
        if(i) ans=(ans+Dfs(0,0,i-1,d-1)%p*Dfs(l1,l2,l3-i,d)%p)%p;
        for(int j=0;j<=l2;j++)
        {
            if(j) ans=(ans+Dfs(0,j-1,i,d-1)%p*Dfs(l1,l2-j,l3-i,d)%p)%p;
            for(int k=1;k<=l1;k++)
                ans=(ans+Dfs(k-1,j,i,d-1)%p*Dfs(l1-k,l2-j,l3-i,d)%p)%p;
        }
    }
    return f[l1][l2][l3][d]=ans;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("Text1.in","r",stdin);
#endif
    L1=read(),L2=read(),L3=read(),D=read();
    Dfs(L1,L2,L3,D); if(D) Dfs(L1,L2,L3,D-1);
    int ans=f[L1][L2][L3][D]-(D?f[L1][L2][L3][D-1]:0);
    printf("%d",(ans+p)%p);
}

转载于:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/10994068.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值