深度优先之铺瓷砖

1. 问题描述:

时间限制:5000ms

单点时限:1000ms

内存限制:256MB

描述

有一长度为N(1<=N<=1000)的地板,给定两种不同瓷砖:一种长度为1,另一种长度为2,数目不限。

要将这个长度为N的地板铺满,一共有多少种不同的铺法?

为了防止溢出,请将结果Mod 1000000007

输入

一个整数N。(1 <= N <= 1000)

输出

铺法的数量Mod 1000000007

样例输入

3

样例输出

3

2. 一看到上面的题目是不是有点似曾相识,跟小白上楼梯的情况类似,只不过是换了一种场景,但是本质上是一样的,我们可以使用递推来解决,我们可以把前面的的瓷砖都铺设好,那么假如只剩下长度为2那么有两种铺设的方法,假如剩下长度为1那么就有一种铺设的方法,其它的长度也类似像这样分析,具体的代码如下:

import java.util.Scanner;
public class Main {
	//这道题目跟上楼梯的题目类似
	static int N;
	static long count = 0;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();
		dfs(N);
		System.out.println(count);
		sc.close();
	}
	private static long dfs(int k) {
		if(k == 1) return count += 1;
        //当剩下来长度为2的时候有两种铺法分别是直接铺设长度为或者铺设长度为2
		if(k == 2) return count += 2;
		return dfs(k - 1) + dfs(k - 2);
	}
}

除了使用递推的方法,我们还可以使用dfs来的解决,其中比较好的是使用dfs可以记录下中间的过程,把所有的组合的情况都记录下来,其中当我们设置dfs出口的时候,当长度等于目标长度的时候就return,假如这个时候没有return的话,那么就还需要再搜索一下它的下一层的元素然后再长度大于目标长度的时候再退出来,那么就会导致不必要的搜索,所以等于目标长度的时候就return了

还需要注意的是记录中间的过程需要溯,这里我们使用动态的数组List来记录中间的过程,即当退回到这一层的时候把这一层原来加入的最后一个元素给清除掉,然后退回到另外一个平行状态下再清除掉原来加入的元素那么其中的List加入的元素才是正确的,这也就是我们所说的回溯,当我们退回到平行状态下,尝试另外一个元素的时候假如这个平行状态对下一个平行状态有影响那么就需要进行回溯,那么才可以得到正确的结果

3. 具体的代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main{
	static int N;
	static int count = 0;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();
		List<Integer> list = new ArrayList<Integer>();
		dfs(0, list);
		System.out.println(count % 1000000007);
		sc.close();
	}
	
	private static void dfs(int k, List<Integer> list){
		if(k == N){
			count++;
			System.out.println(list);
			return;
		}
		if(k > N){
			return;
		}
		list.add(2);
		dfs(k + 2, list);
		list.remove(list.size() - 1);
		list.add(1);
		dfs(k + 1, list);
		list.remove(list.size() - 1);
	}
}

使用dfs来解决是有好处,可以搜索完所有的可能性,但是这也带来了一个问题,也就是耗时的问题,假如只有两个平行状态的情况下,那么在每一次递归调用的时候都会分开两个叉去搜索,所以它是按照指数的方式来增长的,所以来说很耗时,所以虽然提交到代码平台上,对于不大的数字可以通过,但是比较大的数字那么肯定就超时了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值