dp+卡特兰数

Aunt Lizzie takes half a pill of a certain medicine every day. She starts with a bottle that contains N pills.

On the first day, she removes a random pill, breaks it in two halves, takes one half and puts the other half back into the bottle.

On subsequent days, she removes a random piece (which can be either a whole pill or half a pill) from the bottle. If it is half a pill, she takes it. If it is a whole pill, she takes one half and puts the other half back into the bottle.

In how many ways can she empty the bottle? We represent the sequence of pills removed from the bottle in the course of 2N days as a string, where the i-th character is W if a whole pill was chosen on the i-th day, and H if a half pill was chosen (0 <= i < 2N). How many different valid strings are there that empty the bottle?
Input
The input will contain data for at most 1000 problem instances. For each problem instance there will be one line of input: a positive integer N <= 30, the number of pills initially in the bottle. End of input will be indicated by 0.
Output
For each problem instance, the output will be a single number, displayed at the beginning of a new line. It will be the number of different ways the bottle can be emptied.
Sample Input
6
1
4
2
3
30
0
Sample Output
132
1
14
2
5
3814986502092304
#include <iostream>
#include <string.h>
#include "math.h"
#include <algorithm>
using namespace std;
const int maxn=31;

int main() {
    int n;
    long long dp[2*maxn][maxn];//第一个表示的是半个药片的数量,第二个表示的是整个药片的数量
    memset(dp, 0, sizeof(dp));
    for(int i=1;i<maxn;i++){
        dp[i][0]=1;//当整个药片的数量为零时,数量为1
    }
    for(int i=1;i<maxn;i++){
        for(int j=1;j<=i;j++){
            dp[i][j]=dp[i-1][j]+dp[i][j-1];
            //dp[i][j]的数量为吃掉一个半片的数量dp[i-1][j]和吃掉一个整片的数量dp[i][j-1];
        }
    }

    while (scanf("%d",&n),n ){
 
 

printf("%lld\n",dp[n][n]);

}

return 0;

}

这道题还可以用卡特兰数来写

卡特兰数的公式为f[i]=f[i-1]*((i*4-2)/(i+1);

#include <iostream>
#include <string.h>
#include "math.h"
#include <algorithm>
using namespace std;
const int maxn=31;
long long f[maxn];
long long katelan(int n)
{
    if(n==1){
        return 1;
    }
    f[n]=katelan(n-1)*(n*4-2)/(n+1);
    return f[n];
}
int main() {

    int n;
    while (scanf("%d",&n),n){
        printf("%lld\n",katelan(n));
    }
    return 0;
}

还可以用记忆化搜索来写

这个转载....

#include<iostream>
using namespace std;
long long f[32][32];//f[i][j]=剩下i片整药和j片半药时的序列数
long long fun(int x,int y)
{
    long long ans=0;
    if(f[x][y])
        return f[x][y];//如果只有一片药的话直接输出1
    ans+=fun(x-1,y+1);//吃一个整片药,,直到只剩下一片药
    if(y)//出来,把吃整片药换成吃半片药
        ans+=fun(x,y-1);//继续
    return f[x][y]=ans;//记录,不超时的关键,因为递归会递归到有值得地方
}
int main()
{
    int i,n;
    memset(f,0,sizeof(f));
    for(i=0;i<=30;i++)
        f[1][i]=i+1;
    while(scanf("%d",&n)&&n)
    {
        printf("%lld\n",fun(n,0));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/79834043
今日推荐