HDU 5151 Sit sit sit (区间DP)

题目:LINK

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


区间DP,dp[i][j] 表示i~j坐满的不同的情况数.if(t-1 和 t+1 颜色相同) ,dp[i][j] = sum(dp[i][t-1] * dp[t+1][j] * C[j - i][t - i])
表示区间i~j内最后去坐t位置, 乘组合数是因为之前的j - i个去选择座位的机会可以任意选择去坐在左区间或右区间(左右区间i~t-1, t+1~j).
可以用记忆化去写.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std; 
#define INF 1000000000
#define N 111
typedef __int64 LL; 
const LL mod = 1000000007; 
LL dp[N][N], C[N][N]; 
int n, num[N]; 
void init() {
    for(int i = 0; i < N; i++) {
        for(int j = 0; j <= i; j++) {
            if(j == 0 || j == i) C[i][j] = 1; 
            else C[i][j] = (C[i-1][j-1] + C[i-1][j]) % mod; 
        }
    }
}
LL dfs(int L, int R) {
    if(dp[L][R] != -1) return dp[L][R]; 
    if(L == R) return dp[L][R] = 1; 
    dp[L][R] = (dfs(L+1, R) + dfs(L, R - 1)) % mod; 
    for(int i = L+1; i <= R-1; i ++) {
        if(num[i-1] != num[i+1]) continue; 
        dp[L][R] = (dp[L][R] + (dfs(L, i - 1) * dfs(i+1, R) % mod) * C[R- L][i - L]%mod) % mod; 
    }
    return dp[L][R]; 
}
int main() {
    init();
    while(scanf("%d", &n) != EOF) {
        memset(dp, -1, sizeof(dp)); 
        for(int i = 1;i <= n; i++) scanf("%d", &num[i]); 
        printf("%I64d\n", dfs(1, n)); 
    }
    return 0; 
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值