# Dynamic Programming# Recursion# Fibonacci# Memoization

d544 - 1. 海藻(algae)

🔗 前往 ZeroJudge 原題

題目描述

題目描述了一種特殊海藻的生長規則,要求計算第 N 天時,由左邊數來第 K 個分枝的顏色(0 代表綠色,1 代表黃色)。如果第 N 天時,海藻的分枝數少於 K,則輸出 -1。

解題思路

這道題的核心在於理解海藻的生長模式,並將其與斐波那契數列聯繫起來。第 n 天海藻的分枝數等於斐波那契數列的第 n+1 項。 程式碼使用遞迴和動態規劃(memoization)來計算第 n 天第 k 個分枝的顏色。dp(n, k) 函數遞迴地計算顏色。 如果 n 為奇數,則將問題分解為 dp(n-2, k) (如果 k 小於等於第 n-2 天的分枝數) 或 dp(n-1, k - fib[n-2]) (如果 k 大於第 n-2 天的分枝數)。 如果 n 為偶數,則將問題分解為 dp(n-2, k)dp(n-3, k - fib[n-2])dp(n-2, k - fib[n-2] - fib[n-3])fib 陣列預先計算了斐波那契數列的值,用於快速查找第 n 天的分枝數。

複雜度分析

  • 時間複雜度: O(N)
  • 空間複雜度: O(N)

程式碼

#include <iostream>
using namespace std;
long long int fib[49]={0,1};
long long int dp(long long int n,long long int k){
	if(n==1&&k==1)return 0;
	else if(n==2&&k==1)return 1;
	while(n>48)n-=2;
	long long int size=fib[n];
	if(k>size)return -1;
	if(n%2){
		long long int xs=fib[n-2],ys=fib[n-1];
		if(k<=xs){
			return dp(n-2,k);
		}
		else{
			return dp(n-1,k-xs);
		}
	}
	else{
		long long int y1s=fib[n-2],xs=fib[n-3],y2s=fib[n-2];
		if(k<=y1s){
			return dp(n-2,k);
		}
		else if(k<=y1s+xs){
			return dp(n-3,k-y1s);
		}
		else{
			return dp(n-2,k-y1s-xs);
		}
	}
}
int main(){
	for(int i=2;i<49;++i){
		fib[i]=fib[i-1]+fib[i-2];
	}
	long long int m,n,k;
	cin >> m;
	while(m--){
		cin >> n >> k;
		cout << dp(n,k) << "\n";
	}
}

Discussion