Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

การปูกระเบื้องสี่เหลี่ยมจัตุรัสน้อยที่สุดเพื่อปิดสี่เหลี่ยมผืนผ้าใน C++


ให้สี่เหลี่ยมผืนผ้าขนาด n x m หาจำนวนสี่เหลี่ยมจัตุรัสขนาดจำนวนเต็มที่น้อยที่สุดที่สามารถปูครอบคลุมสี่เหลี่ยมผืนผ้าได้

เช่น n=2, m=3 เอาต์พุต = 3 (ต้องใช้ 3 ชิ้น)

วิธีแก้ − ใช้ DFS + Backtracking พร้อม Memoization ลองวางสี่เหลี่ยมจัตุรัสขนาดต่างๆ จากมุมที่ว่างอยู่ต่ำสุด

ตัวอย่าง

#include <bits/stdc++.h> 
using namespace std; 

class Solution { 
public: 
    map<int, int> s; 
    int res = INT_MAX; 
    void dfs(int n, int m, vector<int> h, int cnt){ 
        if (cnt >= res) return; 
        bool isFull = true; 
        int pos = -1, minH = INT_MAX; 
        for (int i = 1; i <= n; i++) { 
            if (h[i] < m) isFull = false; 
            if (h[i] < minH) { minH = h[i]; pos = i; } 
        } 
        if (isFull) { res = min(res, cnt); return; } 
        long key = 0, base = m + 1; 
        for (int i = 1; i <= n; i++) { key += h[i] * base; base *= m + 1; } 
        if (s.find(key) != s.end() && s[key] <= cnt) return; 
        s[key] = cnt; 
        int end = pos; 
        while (end + 1 <= n && h[end + 1] == h[pos] && (end + 1 - pos + 1 + minH) <= m) end++; 
        for (int j = end; j >= pos; j--) { 
            int curH = j - pos + 1; 
            vector<int> next(n + 1); 
            for (int i = 1; i <= n; i++) next[i] = h[i]; 
            for (int k = pos; k <= j; k++) next[k] += curH; 
            dfs(n, m, next, cnt + 1); 
        } 
    } 
    int tilingRectangle(int n, int m){ 
        if (n == m) return 1; 
        if (n > m) swap(n, m); 
        vector<int> h(n + 1); 
        dfs(n, m, h, 0); 
        return res; 
    } 
}; 

main(){ 
    Solution ob; 
    cout << (ob.tilingRectangle(2, 3)); 
}

อินพุต

2,3

เอาต์พุต

3