1. 程式人生 > >HDOJ-2047 阿牛的EOF牛肉串(遞推)

HDOJ-2047 阿牛的EOF牛肉串(遞推)

題目:HDOJ-2047

題目描述:長度為n的字串,包含’E’ ‘O’ ‘F’三個字元(可以只有其中一種或兩種字元),而且不能兩個’ O’ 相鄰,求長度為n時可能的組合數。(0<n<40)

思路:
重點是逆向推導,利用已求到的f(n-1)、f(n-2)…得到f(n)。
一開始想的太複雜了,一直分析到了n+3,如下:
①f(n-2) n-1 : E/F n : E/F/O    得到 f(n-2) * 2 *3
②f(n-3) n-2 : E/F n-1 : 0 n : E/F  得到f(n-3) * 2 * 2
最終得到f(n)=f(n-2)*6+f(n-3)*4,實際上我這是對n-1位置上的兩種情況進行討論了,其實完全沒必要這麼麻煩。

遞推很重要的一點是已求到的f(m) (m<n) 是一定合法的。
①f(n-1) n : E/F 得到f(n-1) * 2
當n位置上是E/F,前n-1個位置只要合法即可,n位置對前n-1個位置不造成任何影響,所以可以直接套用f(n-1)。
②f(n-2) n-1 : E/F n : O 得到f(n-2) * 2 * 1
當n位置上是O,n-1位置只能為E/F,同理前n-2位置直接套用f(n-2)。
最終得到f(n)=f(n-1)*2+f(n-2)*2

其實一道題的遞推公式不止一種形式,不過結果都是一樣的,只是分析過程不同。
逆推通常的思路:對n情況進行討論,對前n-1無影響的情況直接套用f(n-1),若有影響,則繼續討論n-1的情況,以此類推。

貼下程式碼:

#include<iostream>
using namespace std;
int main()
{
	int i, n;
	long long f[41];
	f[1] = 3;
	f[2] = 8;
	for (i = 3; i <= 40; i++)
		f[i] = 2 * f[i - 1] + 2 * f[i - 2];
	while (cin >> n)
	{
		cout << f[n] << endl;
	}
	return 0;
}