【網格 dp】A006_LC_鋪瓷磚(三種切分法)

一、Problem

你是一位施工隊的工長,根據設計師的要求準備爲一套設計風格獨特的房子進行室內裝修。

房子的客廳大小爲 n x m,爲保持極簡的風格,需要使用盡可能少的 正方形 瓷磚來鋪蓋地面。假設正方形瓷磚的規格不限,邊長都是整數。

請你幫設計師計算一下,最少需要用到多少塊方形瓷磚?

在這裏插入圖片描述

輸入:n = 11, m = 13
輸出:6

Constraints:

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

二、Solution

方法一:dp

對於面積爲 i×ji × j 的矩形,我們有三種切法:

  1. 規則切割之:可豎直切一刀
  2. 規則切割之:水平切一刀
  3. 不規則切割之:將一個矩形分成 5 塊,中間那塊面積是1 × 1

在這裏插入圖片描述

  • 定義狀態
    • f[i][j]f[i][j] 表示將大小爲 i×ji × j 的矩形鋪滿至少需要的正方形瓷磚數。
  • 思考初始化:
    • i=jf[i][j]=1i = j,f[i][j] = 1,面積爲 i×ii × i 的矩形就是正方形,因此只用一塊正方形瓷磚即可鋪滿
    • i !=jf[i][j]=INFi\ != j,f[i][j] = INF
  • 思考狀態轉移方程
    • 水平切分:f[i][j]=min(f[i][j],f[q][j]+f[iq][j])f[i][j] = min(f[i][j], f[q][j] + f[i-q][j])q[1,i)q∈[1, i)
    • 垂直切分:f[i][j]=min(f[i][j],f[i][p]+f[i][jp])f[i][j] = min(f[i][j], f[i][p] + f[i][j-p])p[1,j)p∈[1, j)
    • 不規則切分:f[i][j]=min(f[i][j],f[x1][y]+f[x][jy]+f[ix+1][y1]+f[ix][jy+1]+1)f[i][j] = min(f[i][j], f[x-1][y] + f[x][j-y] + f[i-x+1][y-1] + f[i-x][j-y+1] + 1)
  • 思考輸出f[n][m]f[n][m]
class Solution {
    public int tilingRectangle(int n, int m) {
        int INF = 0x3f3f3f3f, f[][] = new int[n+5][m+5];

        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            f[i][j] = i == j ? 1 : INF;
            for (int q = 1; q < i; q++) f[i][j] = Math.min(f[i][j], f[q][j] + f[i-q][j]);
            for (int p = 1; p < j; p++) f[i][j] = Math.min(f[i][j], f[i][p] + f[i][j-p]);
            // 不規則切分
            for (int x = 2; x < i; x++)
            for (int y = 2; y < j; y++)
                 f[i][j] = Math.min(f[i][j], f[x-1][y] + f[x][j-y] + f[i-x+1][y-1] + f[i-x][j-y+1] + 1);
        }
        return f[n][m];
    }
}

複雜度分析

  • 時間複雜度:O(n2×m2)O(n^2 × m^2 )
  • 空間複雜度:O(n×m)O(n × m)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章