有高为1到n的杆子各一根排成一行,从左往右能看见l根,从右往左能看见r根,问可能的方案数。
dp[i][j][k]表示i根高度不同的杆子从左往右能看见j根,从右往左能看见k根,根据高度最低的那根杆子分类。
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 30 + 6;
ll f[maxn][maxn][maxn];/*f[i][l][r]表示i根棍子从左边能看见l根从右边能看见r根*/
/*转移为f[i][l][r] = f[i-1][l-1][r] + f[i-1][l][r-1] + (i-2)*f[i-1][l][r]*/
const int mod = 10056;
ll dfs(int tot,int l,int r)
{
ll & res = f[tot][l][r];
if(res != -1)return res;
if(tot==1&&l==r&&r==1)return res = 1;
else if(tot==1)return res = 0;
res = dfs(tot-1,l-1,r) + dfs(tot-1,l,r-1) + (tot-2)*dfs(tot-1,l,r);
return res;
}
int main(int argc, char const *argv[])
{
int T; scanf("%d",&T);
memset(f,-1,sizeof f);
for(int cas = 1,n; cas <= T; ++cas) {
int a,b;
scanf("%d%d%d",&n,&a,&b);
printf("%lld\n", dfs(n,a,b));
}
return 0;
}