d[i][j][k]表示让高度为1~i的杆子排成一行,从左边看能看到j个,从右边看能看到k个 的方案
状态转移:
case 1:插到左边,则左边看得见右边看不见;d(i-1,j-1,k);
case 2: 插到右边,……;d(i-1,j,k-1);
case 3:插到中间,两边都看不到;d(i-1,j,k)*(i-2);
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
const int maxn = 25;
int n,l,r;
long long d[maxn][maxn][maxn];
int vis[maxn][maxn][maxn];
long long dp(int i,int j,int k)
{
long long &ans = d[i][j][k];
if(vis[i][j][k]) return ans;
vis[i][j][k]=1;
if(i==0||j==0||k==0) return ans=0;
return ans=dp(i-1,j-1,k)+dp(i-1,j,k-1)+dp(i-1,j,k)*(i-2);
}
int main()
{
int t;
scanf("%d",&t);
for(int kase=1;kase<=t;kase++)
{
scanf("%d%d%d",&n,&l,&r);
mem(d);mem(vis);
d[1][1][1]=1;
vis[1][1][1]=1;
printf("%lld\n",dp(n,l,r));
}
return 0;
}
记忆化搜索;动态规划计数~