首页 > 试题广场 >

骨牌铺方格

[编程题]骨牌铺方格
  • 热度指数:3793 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
在2×n的一个长方形方格中,用一个1× 2的骨牌铺满方格,输入n ,输出铺放方案的总数.
例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图:


输入描述:
输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2×n (1≤n≤90)。


输出描述:
对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。
示例1

输入

1<br/>3<br/>2

输出

1<br/>3<br/>2
思路:**还是feibonacci问题。
#include<iostream>
#include <vector>
using namespace std;

int main()
{
    vector<long long> v(91);
    v[1] = 1;
    v[2] = 2;
    for (int i = 3; i < 91; i++)
    {
        v[i] = v[i - 1] + v[i - 2];
    }
    int n;
    while (cin >> n)
    {
        cout << v[n] << endl;
    }
}

发表于 2018-08-12 08:46:45 回复(0)

详细解释
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)。

下面时斐波那契问题的求解:

  • 记录子问题的解,来避免下次遇到相同子问题时的重复计算。
    以斐波那契数列为例子:
    斐波那契数列定义为F0 =1,F1 = 1,Fn = Fn-1+Fn-2(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

3 参考代码

//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;
}
发表于 2020-03-02 10:12:51 回复(0)
不能用递归,时间复杂度太大。用for循环可以解决。注意long long整型防止溢出。

#include<stdio.h>

long long add(int n)
{   
    if(n == 1) return 1;
    if(n == 2) return 2;
    
    long long xip = 1;
    long long foo = 2;
    long long bar;
    
    for(int i = 3; i <= n; i++)
    {
        bar = xip + foo;
        xip = foo;
        foo = bar;
    }
    return bar;
};

int main()
{
    int n = 0;
    while(scanf("%d", &n) != EOF){

    printf("%lld\n", add(n));
    }
    return 0;
}


发表于 2019-08-12 21:42:16 回复(0)

python solutoin

仔细思考,就会发现这本质上是跳台阶的问题。也就是一个Fibonacci数列

import sys


def programsNumber(n):
    arr = [1, 2]
    while len(arr) < n:
        arr.append(arr[-1] + arr[-2])
    return arr[n - 1]


for i in sys.stdin.readlines():
    print(programsNumber(int(i)))
编辑于 2017-11-17 10:13:48 回复(5)
a=[0,1,2]
for i in range(3,91):
	a.append(a[i-1]+a[i-2])

while True: 
	try: 
		c = int(input())
		print(a[c])
	except: 
		break


发表于 2017-09-01 21:43:52 回复(0)
#include<cstdio>
using namespace std;
long ans[91];
int n;
int main(){
	ans[1]=1;
	ans[2]=2;
	for(int i=3 ;i<=90 ;i++){
		ans[i] = ans[i-1] + ans[i-2];
	}
	while(scanf("%d",&n)!=EOF){
		printf("%ld\n",ans[n]);	
	}
	return 0;
} 

发表于 2016-07-09 21:39:12 回复(0)


import java.util.ArrayList;
import java.util.Scanner;

class Solution{

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int count = 0;
int []arr = new int[90];
arr[1]=1;
arr[2]=2;
arr[3]=3;
arr[0] = 0;
ArrayList<Integer> ns = new ArrayList<>();
ArrayList<Integer> ns1 = new ArrayList<>();
do {
 String string = input.nextLine();
 if (string.equals("")) {
   break;
 }
 ns.add(Integer.valueOf(string));
} while (true);
for(int i=0;i<ns.size();i++){
if(ns.size()>3){
for(int j =4;j<ns.get(i);){
arr[j] = arr[j-1]+arr[j-2];
ns1.add(arr[j]);
}
}else{
ns1.add(arr[ns.get(i)]);
}
}
for(int i=0;i<ns1.size();i++){
System.out.println(ns1.get(i));
}
}
}

发表于 2016-04-19 21:14:19 回复(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;
}
题目本质是Fibonacci数的变形。正好最近在学习邓公的数据结构,所以就用上了。时间复杂度为O(n),附加空间为常数规模。
f初始值可以看做fib(-1),g初始值可以看做fib(0)。
发表于 2019-09-10 21:11:29 回复(0)

放第n的时候,可在n-2的情况下在最右边横着放两块,有a[n-2]种情况,也可在n-1的情况下在最右边竖着放一块,有a[n-1]种情况.

故:a[n]=a[n-2]+a[n-1]

def sq(n):
    res = [1,2]
    while len(res)<n:
        res.append(res[-1]+res[-2])
    return res[n-1]

while True:
    try:
        inputs = int(input())
        print(sq(inputs))
    except:break
发表于 2019-07-18 11:41:25 回复(0)
#include<stdio.h>//最后一格只能是竖直放置,最后两格可以横向放置,也可以竖直放置,但竖直
int main()       //放置与最后一个竖直放置重复,故只能横向放置,且了最后一格竖直放置,与
{                //最后两块横向放置,所产生的排列方式一定不相同,所以n格的放置方式
    long n,i,f[91];//等于n-1格加上n-2格。
    f[1]=1;         //若分成3+n-3则又是以另外一种地推方式得到公式,不是febonacii数列
    f[2]=2;
    for(i=3;i<=90;i++)
    {
        f[i]=f[i-1]+f[i-2];
    }
    while(scanf("%ld",&n)!=EOF)
    {
        printf("%lld\n",f[n]);
    }
}

发表于 2019-04-13 12:26:20 回复(0)
/*
 * =====================================================================================
 *
 *       Filename:  10骨牌铺方格.cpp
 *
 *        Version:  1.0
 *        Created:  2018/09/24 12:43:58
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Covfefe
 *   Organization:    Fs-studio
 *   
 *             idea:  斐波那契数列
 *
 * =====================================================================================
 */
#include <stdio.h>
#include <iostream>
using namespace std;
#define FOR(i,n) for(i = 2; i < n; i++)
int main()
{
    int n, i;
    long long F[91];
    F[0] = 1;
    F[1] = 2;
    FOR(i, 90)
        F[i] = F[i - 1] + F[i - 2];
    while (cin >> n)
        cout << F[n - 1] << endl;
    return 0;
}
发表于 2018-09-24 12:47:02 回复(0)
#include<stdio.h>
long fib(int n)
{
    long pre = 1;
    long next = 0;
    long result = 1;
    while(n > 1)
    {
        n--;
        next = pre;
        pre = result;
        result = next + pre;
    }
    return result;
}
int main(void)
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        printf("%ld\n", fib(n));
    }
}


发表于 2018-04-01 16:04:07 回复(0)
#include <stdio.h>
voidDataInit(longlong*a);
intmain()
{
    intN, i;
    longlongA[100001] = {0, 1, 2};
    DataInit(A);
    while(scanf("%d", &N)!=EOF)
    {
        printf("%lld\n", A[N]);
    }
      
    return0;
}
voidDataInit(longlong*a)
{
    inti;
    for(i=3;i<100001;i++)
    {
        a[i] = a[i-1] + a[i-2];
    }
}

发表于 2017-11-26 23:43:21 回复(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]);
        }
    }
发表于 2017-11-05 15:53:01 回复(0)
#include <iostream>
#define N 90
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
    long long n[N];
    n[0] = 1;
    n[1] = 2;
    int i;
    for(i = 2; i < N; i++)
    {
        n[i] = n[i-1] + n[i-2];
    }
    while(scanf("%d", &i) != EOF)
    {
        printf("%lld\n", n[i-1]);
    }
    return 0;
}
//上一道题直接粘到这里就通过了
发表于 2017-03-24 09:01:02 回复(0)
用递归会超时?用int会越界?
编辑于 2016-12-20 20:25:24 回复(0)
其实就是斐济那波数列  长度为n  那么最后三块有两种放置的方式 总计方案为那两种方式的和

import java.util.Scanner;

/**
 * 类描述:
 * http://www.nowcoder.com/questionTerminal/45891d5680e743418faa5accc0544c43
 *
 * @auhter Created by luckyAF on 16/4/19
 */
public class Main  {

    public static  void main(String[] args){
        int simple[] ={1,2,3,5};
        Long array[] = new Long[90];
        array[0] = Long.valueOf(simple[0]);
        array[1] = Long.valueOf(simple[1]);
        array[2] = Long.valueOf(simple[2]);
        array[3] = Long.valueOf(simple[3]);
        for(int i =4; i < 90; i ++){
            array[i] = array[i - 1] + array[i - 2];
        }
        Scanner in = new Scanner(System.in);
        int n;
        while(in.hasNextInt()){
            n = in.nextInt();
            System.out.println(array[n - 1]);
        }

    }

}
发表于 2016-04-20 00:14:11 回复(0)
LLJ头像 LLJ
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];
    }
}

编辑于 2016-04-19 21:32:37 回复(0)
#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;
}


发表于 2016-01-17 18:24:18 回复(0)
#include <stdio.h>
int main()
{
    long long arr[91];
    int i,n;
    arr[1]=1;
    arr[2]=2;
    for(i=3;i<=90;i++)
        arr[i]=arr[i-1]+arr[i-2];
    while(scanf("%d",&n)!=EOF){
        printf("%ld\n",arr[n]);
    }
    return 0;
}


发表于 2015-12-10 21:53:33 回复(0)

问题信息

难度:
21条回答 9233浏览

热门推荐

通过挑战的用户

骨牌铺方格