YbtOJ 遞推演算法課堂過關 例5 平鋪方案【遞推(簡單DP)】

Jackma_mayichao發表於2020-12-25

在這裡插入圖片描述


思路

首先讀題可得設 f [ i ] f[i] f[i] 表示 2 ∗ i 2*i 2i 時的方案數。
因為邊最長是2,所以考慮從 f [ i − 1 ] f[i-1] f[i1] f [ i − 2 ] f[i-2] f[i2] 轉移。
i − 2 i-2 i2 時的情況:
在這裡插入圖片描述
i − 1 i-1 i1 時只有可能有一條豎著的,所以直接繼承 f [ i − 1 ] f[i-1] f[i1]
當然此時存在了重複, i − 2 i-2 i2 的兩條豎著的情況和 i − 1 i-1 i1 的情況發生了衝突,
所以直接把 i − 2 i-2 i2 的情況剔除即可。
需要高精度。

C o d e Code Code

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long f[300][101];
int n,m;
void gjc(int x)
{
	int jw=0;
	for(int i=1; i<=f[x-2][0]+1; i++)
	 {
	 	f[x][i]=(f[x-2][i]*2)%10+jw;
	 	jw=(f[x-2][i]*2)/10;
	 }
	if(f[x][f[x-2][0]+1]!=0)
	  f[x][0]=f[x-2][0]+1;
	else
	  f[x][0]=f[x-2][0];
}
void gjj(int x)
{
	int jw=0;
	for(int i=1; i<=f[x][0]+1; i++)
	 {
	 	int g=(f[x][i]+f[x-1][i]+jw);
	 	f[x][i]=g%10;
	 	jw=g/10;
	 }
	if(f[x][f[x][0]+1]!=0)
	  f[x][0]=f[x-1][0]+1;
}
int main()
{
	f[1][1]=1,f[2][1]=3,f[1][0]=1,f[2][0]=1;
	for(int i=3; i<=250; i++)
	 {
	   gjc(i);
	   gjj(i);
	 }
	//f[i]=f[i-2]*2+f[i-1];
	while(cin>>n)
	 {
	 	int i=f[n][0];
	 	while(f[n][i]==0)
	      i--;
	 	for(int i=f[n][0]; i>=1; i--)
	 	   cout<<f[n][i];
	 	cout<<endl;
	 }
	return 0;
}

相關文章