Problem Description
给你一个柜子,至上往下有n个抽屉,问你恰好s个是安全的,有多少种情况。
例如至上往下第三个是锁着的,但是第二个并不是锁着的。那么第三个不安全,如果第四个是锁着的,那么第四个安全。
如果至上往下第一个是锁着的,那么第一个安全。
思路:
dp[i][j][0]代表着当前i个抽屉,j个安全,最下面那个是不锁着的情况数,dp[i][j][1]代表最下面那个是锁着。
状态转移方程就是:
因为最下面不锁着,所以肯定不增加安全个数。dp[i][j][0] += dp[i-1][j][0] + dp[i-1][j][1]。
因为最下面锁着,所以可能增加可能不增加。
dp[i][j][1] += dp[i-1][j][0] + dp[i-1][j-1][1]。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[70][70][2];
int main()
{
int n, s, i, j;
while(~scanf("%d %d", &n, &s))
{
if(n<0 && s<0) break;
memset(dp, 0, sizeof(dp));
dp[1][1][1] = 1;//最下面是锁着 初始化
dp[1][0][0] = 1;//最下面是不锁着 初始化
for(i = 2; i <= n; i++)
{
for(j = 0; j <= i; j++)
{
dp[i][j][0] += dp[i-1][j][0] + dp[i-1][j][1];
dp[i][j][1] += dp[i-1][j][0];
if(j) dp[i][j][1] += dp[i-1][j-1][1];
}
}
printf("%lld\n", dp[n][s][1]+dp[n][s][0]);
}
return 0;
}