hdu 5151 Sit sit sit(区间dp+排列组合)

题目链接:hdu 5151 Sit sit sit

题意:

一共有并排N个椅子, N个学生依次去坐,同时满足3个条件就不能坐下去:

1,该椅子不在最左,不在最右。

2,该椅子左右都有人坐了。

3,左右的椅子不同颜色。
求最后N个人都能坐下去,有多少不同的情况.

题解:

考虑区间dp,dp[i][j] = sum(dp[i][k-1] * dp[k+1][j] * c[j - i][k - i])其中满足(v[k-1]==v[k+1])

表示i到j区间最后来坐k位置,乘组合是因为合并这两段区间的时候,j-i个人中选择k-i个人去坐左区间的位置,剩下的就坐右区间的位置。

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=a;i<=b;++i)
 4 using namespace std;
 5 typedef long long ll;
 6 const int P=1e9+7,N=107;
 7
 8 ll c[N][N],dp[N][N];
 9 int n,v[N];
10
11 void Init()
12 {
13     for(int i=0;i<=100;i++)
14     {
15         c[i][0]=c[i][i]=1;
16         for(int j=1;j<i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
17     }
18 }
19
20 int main()
21 {
22     Init();
23     while(~scanf("%d",&n))
24     {
25         F(i,1,n)scanf("%d",v+i);
26         mst(dp,0);
27         F(i,1,n)dp[i][i]=1;
28         F(l,2,n)F(i,1,n-l+1)
29         {
30             int j=i+l-1;
31             dp[i][j]=(dp[i+1][j]+dp[i][j-1])%P;
32             F(k,i+1,j-1)if(v[k-1]==v[k+1])
33             {
34                 dp[i][j]=(dp[i][j]+dp[i][k-1]*dp[k+1][j]%P*c[j-i][k-i])%P;
35             }
36         }
37         printf("%lld\n",dp[1][n]);
38     }
39     return 0;
40 }

时间: 2024-11-10 00:20:18

hdu 5151 Sit sit sit(区间dp+排列组合)的相关文章

【HDU】5151 Sit Sit Sit(区间DP+排列组合)

题目大意:可以查阅网站的中文翻译,就不说了,是第24场Best Coder 思路: 这道这道区间DP,我也开始觉得其实区间DP是一种应用型的思想,做这类题目一个重要的点是在于题目情景的把握,这道题的一个情景就是数学的排列组合问题. 首先应用根据小区间推出大区间的思路,我们可以先固定一个位置k,k位置是最后做的位置,那么我们要算出在这种情况下符合的方法数,假如k是头或者尾,那不用说, 此时的方法为dp[i+1][j]或者是dp[i][j-1]; 假如k是有邻居的,那我们就要考虑邻居的颜色,如果颜色

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

做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死. 枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法, (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次 减法同理 乘法特殊一点 (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可 想到这些还远远没有结束,因为最

hdu5396 Expression 区间dp +排列组合

#include<stdio.h> #include<string> #include<map> #include<vector> #include<cmath> #include<stdlib.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int N=105; cons

HDU 4960 Another OCD Patient 区间dp

区间dp.. T^T一直感觉是n^3,看了题解看来是数据水了么.. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string.h> #define ll long long #define inf 1e8 inline int min(int a, int b){return a<b?a:b;} inline void rdl(ll

【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值

[题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一位同学的一门必修课分数不同时视为两种情况不同.n,m<=100,Ui<=10^9. [算法]计数DP+排列组合+拉格朗日插值 [题解]把分数作为状态不现实,只能逐门课考虑. 设$f[i][j]$表示前i门课,有j个同学被碾压的情况数,则有: $$f[i][j]=g(i)\cdot\sum_{k=j

HDU 2476 String painter(区间DP啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476 Problem Description There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can cha

HDU 2476 String painter (区间DP)

题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成b的次数 ans[i]:a从(0,i)变成b(0,i)所需的最小次数 初始化ans[i]=dp[0][i] 如果a[i]==b[i],则ans[i]=ans[i-1]; 由小区间更新到大区间 1 //#pragma comment(linker, "/STACK:167772160")//

【noi 2.6_9288】&amp;【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度)

题意:有m个人有一张50元的纸币,n个人有一张100元的纸币.他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数. 解法:(学习了他人的推导后~) 1.Catalan数的应用7的变形.(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html).P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的. (1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+

hdu 5115 Dire Wolf(区间dp)

Problem Description Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not all, Dire Wolves appear to originate from Draenor. Dire wolves look like normal wolves, but these creatures are of nearly twice th