HDU1267 下沙的沙子有几粒? 基础DP

题目链接

题意:给定m个H和n个D(1<=n,m<=20),问这些字母构成的序列中,对于任意位置,从左开始数H的累积个数总是不比D的累计数少的排列有多少种。

题解:二维DP,画一个正方形,从左上角到右下角画一条线,右上方区域就是我们所要求的。另外注意这个题的输入顺序是先输入m再输入n。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[25][25];
int n,m;
void init()
{
    memset(dp,0,sizeof(dp));
    for(int j=1; j<=20; j++) dp[0][j]=1;
    for(int i=1; i<=20; i++)
        for(int j=i; j<=20; j++)
            dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
int main()
{
    init();
    while(cin>>m>>n)
        cout<<dp[n][m]<<endl;
    return 0;
}

 虽然知道深搜2^40会超时,但还是用深搜写了一发。

#include <bits/stdc++.h>
using namespace std;
int n,m,x,ans,data[1005];
void dfs(int k,int n,int m)
{
    if(k==x)
    {
        int tmp=0;
        for(int i=0; i<k; i++)
        {
            tmp+=data[i];
            if(!data[i]) tmp--;
            if(tmp<0) return;
        }
        if(tmp>=0)
        {
            //for(int i=0; i<k; i++) printf("%d ",data[i]);
            //printf("*
");
            ans++;
        }
        //memset(data,0,sizeof(data));
        return;
    }
    if(n>0)
    {
        data[k]=0; n--;
        dfs(k+1,n,m);
        n++;//这个一定要放到里面
    }

    if(m>0)
    {
        data[k]=1; m--;
        dfs(k+1,n,m);
        m++;
    }
}
int main()
{
    while(cin>>m>>n)
    {
        memset(data,0,sizeof(data));
        x=n+m;
        ans=0;
        dfs(0,n,m);
        cout<<ans<<endl;
    }
    return 0;
}

貌似这道题还可以用公式算:传送门

原文地址:https://www.cnblogs.com/Ritchie/p/5425327.html