分析:这是一道动态规划题,设f[i][j][k]表示走到了第i个位置,遇到了j个花,还剩k斗酒的合法方案数.
初始化很简单就是f[0][0][2]=1,因为一开始酒的数量是2
假如共遇到店n次,遇到花m次:
那么答案就是f[n+m-1][m-1][1],这是很容易理解的,因为我们共需要遇到m次花且最后一次一定是花,则走到倒数第二个位置时一定已经遇到了m-1个花,且由于遇到花后酒的数量会减少1,所以走到倒数第二个位置时酒的数量也必须是1.
下面开始进行状态转移方程的推导:
首先我们有必要对酒的奇偶性进行讨论,因为当走到第i个位置时酒的数量为偶,则第i个位置不可能为店,因为无论是奇数还是偶数,乘以2得到的数都是一个偶数,所以只有当k是偶数时第i个位置才可能是店,假如第i个位置是店,那么这个时候在第i-1个位置的酒的数量就是k/2,而遇到花的数量跟第i-1个位置是一样的都是j,这个很好理解,下面再看一下第i个位置是花的情况,那么第i-1个位置的酒的数量一定是k+1,因为在第i个位置消耗了1,而到达第i个位置遇到的花的数量就要比第i-1个位置遇到花的数量多1,因为我们现在是在假设第i个位置是花。
这就是这道题目的全部分析过程了,下面给出代码:
#include<iostream>
using namespace std;
const int N=113;
const int mod=1e9+7;
long long f[N*2][N][N];//f[i][j][k]表示走到了第i个位置,遇到了j个花,还剩k斗酒的合法方案数
int main()
{
f[0][0][2]=1;//初始化
int n,m;
cin>>n>>m;
for(int i=1;i<n+m;i++)
for(int j=0;j<m;j++)
for(int k=0;k<=m;k++)//酒的数量不能超过花的数量,否则就算之后一直是花也喝不完
{
if(!(k&1))//k是偶数,则第i个位置可以是店,否则不可以是店
f[i][j][k]=(f[i][j][k]+f[i-1][j][k>>1])%mod;
if(j>=1)//无论k是奇数还是偶数,第i个位置都可以是花
f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k+1])%mod;
}
printf("%lld",f[n+m-1][m-1][1]);
return 0;
}