HDU 5151 Sit sit sit 区间dp

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5151

题解:

有n个椅子,编号为1到n。

现在有n个同学,编号为1到n,从第一个同学开始选择要坐的位子,并且这个同学不能坐同时满足下面三个条件的椅子。

1、左右都有相邻的位子

2、左右相邻的位子都是空的。

3、左右两边的位子颜色不同。

问总共有多少种坐法。

题解:

dp[i][j]表示坐满编号为i到j的椅子的类数。

现在第一个开始坐的人选择的是第t个位子,则dp[i][j]+=dp[i][t-1]*dp[t+1][j]*C[j-i][t-i],其中组合数C表示安排t-i个人在左边的组合数。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int mod = 1e9 + 7;
 9 const int maxn = 111;
10 
11 int n;
12 int arr[maxn];
13 LL dp[maxn][maxn],C[maxn][maxn];
14 
15 void pre() {
16     C[0][0] = 1;
17     for (int i = 1; i < maxn; i++) {
18         C[i][0] = 1;
19         for (int j = 1; j <= i; j++) {
20             C[i][j] = (C[i-1][j - 1] + C[i - 1][j]) % mod;
21         }
22     }
23 }
24 
25 LL dfs(int i, int j) {
26     if (i == j) return dp[i][j] = 1;
27     if (i > j) return 0;
28     if (dp[i][j] != -1) return dp[i][j];
29     LL &ret = dp[i][j] = 0;
30     ret=(ret+dfs(i + 1, j)+dfs(i, j - 1))%mod;
31     for (int mid = i + 1; mid <= j - 1; mid++) {
32         if (arr[mid - 1] ^ arr[mid + 1]) continue;
33         ret =(ret+dfs(i, mid - 1)*dfs(mid + 1, j)%mod*C[j - i][mid - i])%mod;
34     }
35     return ret;
36 }
37 
38 void init() {
39     memset(dp, -1, sizeof(dp));
40 }
41 
42 int main() {
43     pre();
44     while (scanf("%d", &n) == 1 && n) {
45         init();
46         for (int i = 1; i <= n; i++) scanf("%d", arr + i);
47         LL ans=dfs(1, n);
48         printf("%lld
", ans);
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/fenice/p/5515880.html