(第13回ブルーブリッジカップ州大会)I:李白のワイン強化版(動的計画法)

1e9+7を法とする出力回答

サンプル入力

5 10

サンプル出力

14

分析:これは動的計画問題です。f[i] [j] [k]は、i番目の位置に到達し、j個の花に遭遇し、k個の法的な解が残っていることを意味します。

初期化は非常に簡単です。最初はワインの数が2であるため、f [0] [0] [2]=1です。

店舗に合計n回、花にm回遭遇した場合:

答えはf[n+ m-1] [m-1] [1]です。これは、合計m個の花に遭遇する必要があり、最後の花は花でなければならないため、理解しやすいです。次に、最後から2番目に移動します。 1位置では、m-1の花に遭遇している必要があり、花に遭遇するとワインの数が1減少するため、最後から2番目の位置に到達したときのワインの数も1である必要があります。

状態遷移方程式の導出を始めましょう:

まず、ワインのパリティについて議論する必要があります。なぜなら、i番目の位置に達したときにワインの数が偶数の場合、i番目の位置は奇数かどうかにかかわらず店舗になることができないからです。偶数、2を掛けた数偶数なので、kが偶数の場合に限り、i番目の位置が店舗になります。i番目の位置が店舗の場合、ワインの数はこのときのi-1位はk/2で、i位が店舗の場合i-1位までの花の数はjと同じでわかりやすいので、 i番目の位置が花である状況を見ると、i番目の位置で1が費やされているため、i-1番目の位置のワインの数はk。+1でなければなりません。 i番目の位置は花の数より1多いです。これは、i番目の位置を想定しているためです。場所は花です。

これは、このトピックの分析プロセス全体です。コードを以下に示します。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#include<vector>
#include<map>
#include<queue>
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; 
}

おすすめ

転載: blog.csdn.net/AC__dream/article/details/124072351
おすすめ