POJ 3934 Queue(DP)

Queue

Description

Linda is a teacher in ACM kindergarten. She is in charge of n kids. Because the dinning hall is a little bit far away from the classroom, those n kids have to walk in line to
the dinning hall every day. When they are walking in line, if and only if two kids can see each other, they will talk to each other. Two kids can see each other if and only if all kids between them are shorter then both of them, or there are no kids between
them. Kids do not only look forward, they may look back and talk to kids behind them. Linda don’t want them to talk too much (for it’s not safe), but she also don’t want them to be too quiet(for it’s boring), so Linda decides that she must form a line in which
there are exactly m pairs of kids who can see each other. Linda wants to know, in how many different ways can she form such a line. Can you help her?

Note: All kids are different in height.

Input

Input consists of multiple test cases. Each test case is one line containing two integers. The first integer is n, and the second one is m. (0 < n <= 80, 0 <= m <= 10000).

Input ends by a line containing two zeros.

Output

For each test case, output one line containing the reminder of the number of ways divided by 9937.

Sample Input

1 0
2 0
3 2
0 0

Sample Output

1
0
4

题意  linda在一个幼儿园当老师  他要把n个学生排成一列  使仅仅有m对学生可以讲话   当两个学生相邻或者他们之间的全部人都比他们矮时   他们就行讲话

每一个学生的身高都不同

令d[i][j]表示把i个学生排成一列使j对学生可以讲话的方法数

能够把i个学生分成i-1个学生和一个最矮的学生  把这个学生放在i-1个学生中随意两个学生之间都不会影响原来的结果  可是能讲话的学生对数添加了2  有i-2种放法

或者把这个最矮的学生放在两边  这样能讲话的对数仅仅添加了1   有两种放法

所以有转移方程d[i][j]=d[i-1][j-2]*i-2+d[i-1][j-1]*2(j>=2)

j<2时仅仅有d[1][0]=1(学生数大于1就有相邻的就能讲话了) 和d[2][1]=2(学生数大于2肯定不止一对能讲话了)两个有值  能够作为初始条件

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 81, M = 10001;
int d[N][M], n, m;
int main()
{
    d[1][0] = 1, d[2][1] = 2;
    for (int i = 1; i < N; ++i)
        for (int j = 2; j < M; ++j)
            d[i][j] = (d[i - 1][j - 2] * (i - 2) + 2 * d[i - 1][j - 1]) % 9937;

    while (scanf ("%d%d", &n, &m), n)
        printf ("%d\n", d[n][m]);

    return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-08-10 17:19:48

POJ 3934 Queue(DP)的相关文章

周赛 POJ 3934 Queue

Description Linda is a teacher in ACM kindergarten. She is in charge of n kids. Because the dinning hall is a little bit far away from the classroom, those n kids have to walk in line to the dinning hall every day. When they are walking in line, if a

poj 3342(树形dp)

题意:在一个公司中要举办一个聚会,每一个员工有一个奉献值.为了和谐规定直接上下级不能一起出席.让你找出奉献值之和最大为多少. 思路:dp[v][1]表示当前结点选,能获得的最大奉献值,dp[v][0]表示当前节点不选能获得的最大奉献值.状态转移: dp[v][0] = max(dp[v][0], ∑max(dp[x][1], dp[x][0]))x为直接儿子 dp[v][1] = max(dp[v][1], ∑dp[x][0] + vex[v]) 最后答案是max(dp[root][0], dp

poj 2151 概率dp

//poj 2151 概率dp 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 double dp[33][33]; 7 int M, T, N; //problem, team, least 8 double p[1010][33]; 9 int mai

POJ 2250 Compromise (DP,最长公共子序列)

Compromise Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6440 Accepted: 2882 Special Judge Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfille

poj 1947(树形dp)

题意:一棵树上问你最少切掉几条边使得能分割出一个结点数正好为k的子树. 思路:dp[i][j]表示以i为根切掉j个结点最少要几条边. dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 代码如下: 1 dp[v][j] = min(dp[v][j], dp[v][j-k] + dp[x][k]); 2 } 3 } 4 } 5 } 6 } 7 return vex[v]; 8 } 9 10 int main() 11 { 12 // freopen("

POJ 2486 树形DP

有一颗苹果树,每个节点上面有很多苹果,从一个节点到另外一个可以到达的节点花费1步,求k步最多能吃到多少苹果,起始点为1,可以不回到起始点. 这是典型的回溯型树状dp. dp[i][j][0]代表以i为根节点的子树最多j步后回到i能吃到的最多的苹果, dp[i][j][1]代表以i为根节点的子树最多j步后不回到i节点最多能吃到的子树.那么状态转移就分三步了. (1)dp[i][j+2][0] = max(dp[i][j+2][0], dp[i][j-k][0]+dp[son][k][0]); (2

POJ 2411 插头DP

1 //插头DP,算是广义路径的吧. 2 /* 3 我是这样想的,定义填数的为0,未填的为1.然后,初始自然是(0,0).我还定义了整个棋盘的状态,不知是否多此一举. 4 这样,把轮廓线上的格子状态记录.当(I,J)上方的格子为空,必定要填一个竖的.当左边格子为空,当前可填一个横的,也可不填. 5 当左边格子不为空,当前格子必为空...AC. 6 */ 7 8 #include <iostream> 9 #include <cstdio> 10 using namespace st

poj 1458 动态规划DP

//  poj 1458  zoj 1733  最长公共子序列  DP #include <iostream>#include <string.h>#define N 1005using namespace std ;char  s1[N],s2[N];   int dp[N][N];int max(int a,int b)   {    return a>b ? a : b ;  }void f(int n,int m){   int i,j;    for (i=0; i

POJ 1925 Spiderman(DP)

题目链接 题意 : Spiderman从最左边的楼通过将蛛丝粘到后边的某座楼顶,然后荡过去,接着发射蛛丝荡过去,直到到达最后的楼.问最少发射几次蛛丝. 思路 :从横坐标 j 能跳过建筑物 i 需满足: (p[i].x - j)*(p[i].x - j) <= p[i].y*p[i].y  - (p[i].y - p[0].y)*(p[i].y-p[0].y). 从横坐标 j 经建筑物 i 后 到达横坐标 2 * p[i].x - j. 所以状态转移方程是: dp[2 * p[i] .x- j]