题意:给定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; }
貌似这道题还可以用公式算:传送门。