码迷,mamicode.com
首页 > 其他好文 > 详细

HDU--5396(区间dp+排列组合)

时间:2015-08-28 23:26:12      阅读:445      评论:0      收藏:0      [点我收藏+]

标签:


做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死。


       枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法,
                (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次
                减法同理
                乘法特殊一点
                (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可

想到这些还远远没有结束,因为最后两个区间合并的时候,还牵扯到一个顺序问题,一开始还好傻好天真直接乘了2,结果呵呵哒了。

  如果共有N个符号,i左边x个,右边y个,那么因为枚举了i这个最后合并的位置,所以最后一个进行运算的符号是确定的,处理完左右的得出的数字分别被加过多少次之后,还要处理这个得出的总数因为合并的顺序不同被多加过多少次,就是C(N-1,x) 其中选出的这x个位置中保持i左边符号的相对顺序不变,因为之前变过顺序的那个前面已经处理过了。。自己理解这里一开始有点问题,总是混,特别怕dp计数,尤其跟排列组合混起来,感觉脑子差一截……


#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <map>
#include <utility>
#include <algorithm>
#include <iostream>
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f
using namespace std;
int dx[]= {-1,0,1,0};///n e s w
int dy[]= {0,1,0,-1};
typedef long long ll;
typedef pair<int,int> pii;
const int maxd=200+5;
///==============================
const int mod=1000000007;
ll dp[maxd][maxd],a[maxd],fac[maxd],c[maxd][maxd];
int n;
char str[maxd];

void init()
{
    fac[0]=1;
    for(int i=1; i<maxd; i++)
        fac[i]=fac[i-1]*i%mod;

    mem(c,0);
    for(int i=0; i<maxd; i++)
    {
        c[i][0]=1;
        for(int j=1; j<=i; j++)
            (c[i][j]=c[i-1][j-1]+c[i-1][j])%=mod;
    }
}

ll dfs(int l,int r)
{
    ll &res=dp[l][r];
    if(res!=mod) return res;

    if(l==r)
        return res=a[l];

    res=0;
    for(int i=l; i<r ; i++)
    {
        ll tmp;
        if(str[i]=='*')
            tmp=dfs(l,i)*dfs(i+1,r)%mod;
        else if(str[i]=='-')
            tmp=(dfs(l,i)*fac[r-i-1]-dfs(i+1,r)*fac[i-l]+mod)%mod;
        else if(str[i]=='+')
            tmp=(dfs(l,i)*fac[r-i-1]+dfs(i+1,r)*fac[i-l])%mod;

        res=(res+tmp*c[r-l-1][i-l]+mod)%mod;
    }
    return res;
}

int main()
{
    int kase;
    freopen("in.txt","r",stdin);
    init();
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; i++)
            scanf("%lld",&a[i]);
        scanf("%s",str);

        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                dp[i][j]=mod;

        cout<<(dfs(0,n-1)+mod)%mod<<endl;
    }
    return 0;
}
/*

3
3 2 1
-+
5
1 4 6 8 3
+*-*
5
1 1 1 1 1
****

*/


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU--5396(区间dp+排列组合)

标签:

原文地址:http://blog.csdn.net/whoisvip/article/details/47777465

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!