[Leetcode週間のレース160] 1240タイル張り

1240は最少二乗で四角形をタイリング铺瓷砖

問題の説明

あなたは、室内装飾のための準備ができて建設チームの職長は、デザイナーの要件に応じて、ユニークなデザインスタイルの家のセットです。

ハウスリビングルームのサイズnX- m、ミニマリストスタイルを維持するために、あなたはいくつかのように使用する必要がある平方毛布にタイル地面を。

いずれの仕様は、正方形のタイル辺の長さが整数であると仮定します。

正方形のタイルのブロックの最小数を計算するためにしてくださいヘルプの設計者は、使用する必要がありますか?

例1:

入力: N- = 2、M = 3。
出力: 3
**解释:**3土地の一部がタイル寝室で覆うことができます。
2ブロック1x1 地砖
1ブロック2x2 地砖

例2:

入力:。N- = 5、M = 8
出力: 5

例3:

入力:。N- = 11、M = 13である
出力: 6

ヒント:

  • 1 <= n <= 13
  • 1 <= m <= 13

思考

  • タイトル読んで
    使用して、部屋のN * Mの固定面積与えられた正方形だけで埋めるタイルを、タイル可変長、タイルに必要な数最小を

コンプライアンスを達成するための行動アウト貪欲な思考+ +例外ルール

  • 貪欲
    正方形選択分割(最大長さ当たりの電流の最適なソリューション、それによって2つのブロックに分割する)、最大の長さを分割正方形貪欲を選択し続けるの一方
  • 調節移動可能
    各ブロックは2つのサブブロックに分割することができ、ブロック細胞分裂し続けることができる- > セルブロックより大きなブロックをマージすることにより最適なソリューション
  • 特例
    11*13这个区块 最优解不能完全分割成两个不相关的区块

dp公式

  • 一般区块的最优解分3种情况:
    1. N=1 或者 M=1 即只能平铺1*1的方块 M或N个
    2. N=M 直接一步到位 铺上N*N的方块 1个
    3. 其他情况 将区块横着切分或者竖着切分 找到最小的那个方案

打表法

因为运算的数据量不大 13*13
可以手动生成全局答案

[1,  2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
[2,  1, 3, 2, 4, 3, 5, 4, 6, 5,  7,  6,  8]
[3,  3, 1, 4, 4, 2, 5, 5, 3, 6,  6,  4,  7]
[4,  2, 4, 1, 5, 3, 5, 2, 6, 4,  6,  3,  7]
[5,  4, 4, 5, 1, 5, 5, 5, 6, 2,  6,  6,  6]
[6,  3, 2, 3, 5, 1, 5, 4, 3, 4,  6,  2,  6]
[7,  5, 5, 5, 5, 5, 1, 7, 6, 6,  6,  6,  6]
[8,  4, 5, 2, 5, 4, 7, 1, 7, 5,  6,  3,  6]
[9,  6, 3, 6, 6, 3, 6, 7, 1, 6,  7,  4,  7]
[10, 5, 6, 4, 2, 4, 6, 5, 6, 1,  6,  5,  7]
[11, 7, 6, 6, 6, 6, 6, 6, 7, 6,  1,  7,  6]
[12, 6, 4, 3, 6, 2, 6, 3, 4, 5,  7,  1,  7]
[13, 8, 7, 7, 6, 6, 6, 6, 7, 7,  6,  7,  1]

代码实现

动态规划

public class Solution {
    private static int size = 13;
    private static int[][] dp = new int[size + 1][size + 1];

    static {
        // 初始化为-1 表示没有被修改
        for (int i = 1; i <= size; i++) {
            Arrays.fill(dp[i], -1);
        }

        for (int i = 1; i <= size; i++) {
            // i*1 or 1*i 面积的铺瓷砖数量
            dp[i][1] = i;
            dp[1][i] = i;
            // i*i 面积的铺瓷砖数量
            dp[i][i] = 1;
        }

        // 唯一的特殊情况 11*13 or 13*11 面积的铺瓷砖数量 不符合贪心规则
        int specialCaseW = 11, specialCaseH = 13, specialCaseR = 6;
        dp[specialCaseH][specialCaseW] = specialCaseR;
        dp[specialCaseW][specialCaseH] = specialCaseR;
    }

    public int tilingRectangle(int n, int m) {
        return helper(n, m);
    }

    private int helper(int n, int m) {
        if (dp[n][m] != -1) {
            return dp[n][m];
        }

        // 最大分块 n*m个1*1方块
        int res = n * m, tmp;
        // 横着切 
        for (int i = 1; i < n; i++) {
            tmp = helper(i, m) + helper(n - i, m);
            res = Math.min(res, tmp);
        }
        // 竖着切
        for (int i = 1; i < m; i++) {
            tmp = helper(n, i) + helper(n, m - i);
            res = Math.min(res, tmp);
        }

        // 备忘录 n*m == m*n
        dp[n][m] = dp[m][n] = res;
        return res;
    }
}

参考资源

第 160 场周赛 全球排名
力扣周赛录屏-leetcode-weekly-contest-160

おすすめ

転載: www.cnblogs.com/slowbirdoflsh/p/11823525.html