例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图:
.jpg)
输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2×n (1≤n≤90)。
对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。
1<br/>3<br/>2
1<br/>3<br/>2
详细解释
https://blog.csdn.net/qq_33375598/article/details/104605811
以下为上述博文中的内容,谢谢支持!
当n为1和2时,情况分别是1,2,当n为3时,就是在前面的基础上增加,如下图所示。
当n为4时,就是下面这种情况:
依次递推。不过本质就是斐波那契数列问题,初值为F(1)= 1,F(2) = 2,公式为F(n) = F(n -1)+F(n-2)。
下面时斐波那契问题的求解:
int F(int n){ if(n == 0 || n == 1) return 1; else return F(n-1) + F(n-2); }
这个递归会涉及到很多重复的计算,如当n==5时,可以得到F(5)= F(4)+F(3),接下来计算F(4)时又会有F(4)= F(3)+F(2),这时不采取措施,F(3)将会被计算两次。如果n很大,重复计算的次数将难以想象。
实际上由于没有保存中间计算的结果,实际复杂度将会高达O(2^n^),即每次都会计算F(n-1)和F(n-2)这两个分支,基本上不能承受n较大的情况。
开一个数组dp,用来保存已经计算过的结果,其中dp[n]记录F(n)的结果,并用dp[n] = -1来表示F(n) 当前还没有被计算过。
int dp[MAXN];
然后就可以在递归中判断dp[n]是否是-1,如果不是-1,说明已经计算过F(n),直接返回dp[n]就是结果;否则,按照递归式进行递归。
int F(int n){ if(n == 0 || n == 1) return 1; if(dp[n] != -1) return dp[n]; else{ dp[n] = F(n-1) + F(n-2); return dp[n]; } }
通过记忆化搜素,把复杂度从O(2^n^)降到O(n)。
斐波那契数列递归图:
斐波那契数列记忆化搜索示意图:
如计算F(45),直接使用递归用时9.082809,用记忆化搜索仅仅0.000001
//https://blog.csdn.net/qq_33375598/article/details/104605811 #include <cstdio> (802)#include <cstring> typedef long long ll; const int MAXN = 10000; ll dp[MAXN]; ll F(int n){//动态规划的递推写法 if(n == 1) return 1; if(n == 2) return 2; if(dp[n] != -1) return dp[n];//记忆化搜素 else{ dp[n] = F(n - 1) + F(n - 2); return dp[n]; } } int main(int argc, char const *argv[]){ int n; while(scanf("%d", &n) != EOF){ memset(dp, -1, sizeof(dp)); printf("%lld\n", F(n)); } return 0; }
#include <iostream> using namespace std; int main() { unsigned long n; while(cin >> n){ unsigned long f = 0, g = 1; while (0 < n--) { g += f; f = g - f; } cout << g << endl; } return 0; }
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
while (s.hasNext()) {
int x = s.nextInt();
long a[] = new long[x + 2];
a[1] = 1;
a[2] = 2;
if (x > 2) {
for (int i = 3; i <= x; i++) {
a[i] = a[i - 1] + a[i - 2];
}
}
System.out.println(a[x]);
}
}
import java.util.Scanner; public class Main { private static long[] a = new long[91]; private static int min = 4; static { a[1]=1;a[2]=2;a[3]=3;a[4]=5; } public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextInt()) {// int n = in.nextInt(); System.out.println(cal(n)); } in.close(); } private static long cal(int n) { if(min < n) { int i = min; while(++i <= n) { a[i] = a[i - 2] + a[i - 1]; } } return a[n]; } }
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(){ long long a[91]; a[1]=1;a[2]=2; a[3]=3;a[4]=5; int min=4; int n; while((scanf("%d",&n))!=EOF){ if(n>min){ for(int i=min+1;i<=n;i++){//根据需求动态计算所需结果,并且随着程序运行时间越来越差, //数据库会越发完善 a[i]=a[i-1]+a[i-2]; } } printf("%lld\n",a[n]); } return 0; }