HDU 5151Sit sit sit

来源:互联网 发布:期货tick数据下载 编辑:程序博客网 时间:2024/06/05 05:00

一道区间DP题,某次BestCoder的B题,想了很久没想出来。

题目描述:一共有并排N个椅子, N个学生依次去坐,同时满足3个条件就不能坐下去:1,该椅子不在最左,不在最右,2,该椅子左右都有人坐了,3,左右的椅子不同颜色
求最后N个人都能坐下去,有多少不同的情况.

题解:dp[i][j]表示排完区间[i,j]的种类数,(看别人题解时没想明白,人是按顺序先后决定坐的位置,即在区间[i,j]内座位的先后序。当[i,j]->[1,n]时,dp的种类数不就是n个人按顺序先后决定坐的位置的种类

转移方程:  dp[i][j] = SUM ( dp[i][k-1]*dp[k+1][j]* C[j-i][i-k] )        其中v[k-1]==v[k+1],保证最后的那个最为合法。乘以组合数的原因是在j-i个人中决定坐前一个区间的人(选完之后,他们是有序的)。

代码君:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>const int N = 100+10;const int mod = 1e9+7;typedef long long ll;ll dp[N][N];int a[N];ll C[N][N];void init(){    for(int i=0;i<=100;i++) C[i][0] = 1;    for(int i=1;i<=100;i++)        for(int j=1;j<=i;j++)            C[i][j] =( C[i-1][j-1] + C[i-1][j] )%mod;}ll dfs(int i,int j){    if(i>j) return 0;    if(i==j) return dp[i][j]=1;    if(dp[i][j]!=-1) return dp[i][j];    ll ans = 0;    ans =( dfs(i+1,j) + dfs(i,j-1) )%mod;    for(int k=i+1;k<=j-1;k++)    {        if(a[k-1]!=a[k+1]) continue;        ans = ( ans + dfs(i,k-1)*dfs(k+1,j)%mod*C[j-i][k-i]%mod)%mod;    }    return dp[i][j] = ans;}int main(){    int n;    init();    while(scanf("%d",&n)!=EOF)    {        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        memset(dp,-1,sizeof(dp));        ll ans = dfs(1,n);        printf("%lld\n",ans);    }    return 0;}



0 0
原创粉丝点击