一天算法题(2019-12-4)

问题

参考博客
参考博客
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
在这里插入图片描述
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。

动态规划:

我们分为两种(假如a[i]表示2*i的格子从刷完所有格子的方案数(其中i表示列数,1<=i<=N))

  1. 从边角出发
  • 从任意一个角出发(假设先从左上角出发,把结果*4就能得到四个角情况了)
  • 第一种情况先把第一列刷完,再刷第二列,这样第一列到第二列有两个选择(要么对角,要么不是对角),记c[i]为从i-1跑到i列的情况数,那么c[i] = a[i-1]*2,然后剩下的格子又是一个全新的子问题
    在这里插入图片描述
  • 第二种情况,不先刷左下角,那么第二次就会刷第二列,这里又分成两种情况:
    第1,任意刷第二列的一个,然后回到第一列刷完,再回到第二列,然后下一列
    在这里插入图片描述
    从上面可以看出,去到第三列可以有四种方法,记这种走到i列的为e[i],则e[i] = 4*a[i-2],然后剩下又是一个全新的子问题
    第2,刷第二列的任意一个,然后不回到第一列,继续刷第三列的任意一个,这样只能不断往下走,不到尽头,不能返回
    在这里插入图片描述
    可以看出,每一次走往下一列,都有两种选择,记走到第i列为d[i],则d[i] = 2^i,d[i] = d[i-1]*2
那么四个角的所有情况为 4*(a[i] = 2 * a[i - 1] + 4 * a[i - 2] + b[i] )
  1. 从中间出发
    起点在i那么两种情况
  • 向左运动后回到第i列然后向右运动
  • 向右运动后回到第i列然后向左运动
    在这里插入图片描述
    代码:(待补)
 private static void paintWalls(int n) {
        long[] d = new long[n + 1];
        long[] a = new long [n + 1];

        d[1] = 1;
        d[2] = 2;

        //a[n]表示起点为某一角落长度为n终点任意的情况数
        a[1] = 1;
        a[2] = 6;
        for (int i = 3; i <= n; i++) {
            d[i] = (2 * d[i - 1]) % MOD;
            a[i] = (2 * a[i - 1] + d[i] + 4 * a[i - 2]) % MOD;
        }
        long ans = 4*a[n];
        for (int i=2;i<n;i++){
            ans = (ans + 8*a[i-1]*d[n-i])%MOD;
            ans = (ans + 8*a[n-i]*d[i-1])%MOD;
        }
        if (n == 1){
            System.out.println(2);
            return;
        }
        if (n == 2){
            System.out.println(24);
            return;
        }
        System.out.println(ans);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值