📜  将一块木板切成正方形的最低成本

📅  最后修改于: 2021-10-26 05:11:58             🧑  作者: Mango

给定一块长 m 宽 n 的木板,我们需要将这块木板分成 m*n 个正方形,以使破坏成本最小。将为板提供每个边缘的切割成本。简而言之,我们需要选择这样一个切割顺序,使成本最小化。
例子:

For above board optimal way to cut into square is:
Total minimum cost in above case is 42. It is 
evaluated using following steps.

Initial Value : Total_cost = 0
Total_cost = Total_cost + edge_cost * total_pieces

Cost 4 Horizontal cut         Cost = 0 + 4*1 = 4
Cost 4 Vertical cut        Cost = 4 + 4*2 = 12
Cost 3 Vertical cut        Cost = 12 + 3*2 = 18
Cost 2 Horizontal cut        Cost = 18 + 2*3 = 24
Cost 2 Vertical cut        Cost = 24 + 2*3 = 30
Cost 1 Horizontal cut        Cost = 30 + 1*4 = 34
Cost 1 Vertical cut        Cost = 34 + 1*4 = 38
Cost 1 Vertical cut        Cost = 38 + 1*4 = 42

这个问题可以用贪心法来解决,如果总成本用S表示,那么S = a1w1 + a2w2 … + akwk,其中wi是某个切边的成本,ai是对应的系数,系数ai由总和决定我们在切割过程结束时使用边缘 wi 竞争的切割次数。请注意,系数的总和始终是常数,因此我们希望找到可得到的 ai 分布,使得 S 最小。为此,我们尽可能早地对成本最高的边执行切割,这将达到最优 S。如果我们遇到多个成本相同的边,我们可以先切割其中的任何一条。
下面是使用上述方法的解决方案,首先我们以相反的顺序对边缘切割成本进行排序,然后我们将它们从高成本循环到低成本构建我们的解决方案。每次我们选择一条边,对应计数加1,每次都要乘以相应的边切割成本。
注意下面使用了 sort 方法,将greater() 作为第三个参数发送到 sort 方法以非递增顺序对数字进行排序,它是库的预定义函数。

C++
//  C++ program to divide a board into m*n squares
#include 
using namespace std;
 
// method returns minimum cost to break board into
// m*n squares
int minimumCostOfBreaking(int X[], int Y[], int m, int n)
{
    int res = 0;
 
    //  sort the horizontal cost in reverse order
    sort(X, X + m, greater());
 
    //  sort the vertical cost in reverse order
    sort(Y, Y + n, greater());
 
    //  initialize current width as 1
    int hzntl = 1, vert = 1;
 
    //  loop until one or both cost array are processed
    int i = 0, j = 0;
    while (i < m && j < n)
    {
        if (X[i] > Y[j])
        {
            res += X[i] * vert;
 
            //  increase current horizontal part count by 1
            hzntl++;
            i++;
        }
        else
        {
            res += Y[j] * hzntl;
 
            //  increase current vertical part count by 1
            vert++;
            j++;
        }
    }
 
    // loop for horizontal array, if remains
    int total = 0;
    while (i < m)
        total += X[i++];
    res += total * vert;
 
    // loop for vertical array, if remains
    total = 0;
    while (j < n)
        total += Y[j++];
    res += total * hzntl;
 
    return res;
}
 
//  Driver code to test above methods
int main()
{
    int m = 6, n = 4;
    int X[m-1] = {2, 1, 3, 1, 4};
    int Y[n-1] = {4, 1, 2};
    cout << minimumCostOfBreaking(X, Y, m-1, n-1);
    return 0;
}


Java
// Java program to divide a
// board into m*n squares
import java.util.Arrays;
import java.util.Collections;
 
class GFG
{
    // method returns minimum cost to break board into
    // m*n squares
    static int minimumCostOfBreaking(Integer X[], Integer Y[],
                                                 int m, int n)
    {
        int res = 0;
     
        // sort the horizontal cost in reverse order
        Arrays.sort(X, Collections.reverseOrder());
     
        // sort the vertical cost in reverse order
        Arrays.sort(Y, Collections.reverseOrder());
     
        // initialize current width as 1
        int hzntl = 1, vert = 1;
     
        // loop until one or both
        // cost array are processed
        int i = 0, j = 0;
        while (i < m && j < n)
        {
            if (X[i] > Y[j])
            {
                res += X[i] * vert;
     
                // increase current horizontal
                // part count by 1
                hzntl++;
                i++;
            }
            else
            {
                res += Y[j] * hzntl;
     
                // increase current vertical
                // part count by 1
                vert++;
                j++;
            }
        }
     
        // loop for horizontal array,
        // if remains
        int total = 0;
        while (i < m)
            total += X[i++];
        res += total * vert;
     
        // loop for vertical array,
        // if remains
        total = 0;
        while (j < n)
            total += Y[j++];
        res += total * hzntl;
     
        return res;
    }
     
    // Driver program
    public static void main(String arg[])
    {
        int m = 6, n = 4;
        Integer X[] = {2, 1, 3, 1, 4};
        Integer Y[] = {4, 1, 2};
        System.out.print(minimumCostOfBreaking(X, Y, m-1, n-1));
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python program to divide a board into m*n squares
 
# Method returns minimum cost to 
# break board into m*n squares
def minimumCostOfBreaking(X, Y, m, n):
 
    res = 0
 
    # sort the horizontal cost in reverse order
    X.sort(reverse = True)
 
    # sort the vertical cost in reverse order
    Y.sort(reverse = True)
 
    # initialize current width as 1
    hzntl = 1; vert = 1
 
    # loop until one or both
    # cost array are processed
    i = 0; j = 0
    while (i < m and j < n):
     
        if (X[i] > Y[j]):
         
            res += X[i] * vert
 
            # increase current horizontal
            # part count by 1
            hzntl += 1
            i += 1
         
        else:
            res += Y[j] * hzntl
 
            # increase current vertical
            # part count by 1
            vert += 1
            j += 1
 
    # loop for horizontal array, if remains
    total = 0
    while (i < m):
        total += X[i]
        i += 1
    res += total * vert
 
    #loop for vertical array, if remains
    total = 0
    while (j < n):
        total += Y[j]
        j += 1
    res += total * hzntl
 
    return res
     
# Driver program
m = 6; n = 4
X = [2, 1, 3, 1, 4]
Y = [4, 1, 2]
 
print(minimumCostOfBreaking(X, Y, m-1, n-1))
 
 
# This code is contributed by Anant Agarwal.


C#
// C# program to divide a
// board into m*n squares
using System;
 
class GFG
{
    // method returns minimum cost to break board into
    // m*n squares
    static int minimumCostOfBreaking(int[] X, int[] Y,
                                        int m, int n)
    {
        int res = 0;
     
        // sort the horizontal cost in reverse order
        Array.Sort(X, new Comparison(
                (i1, i2) => i2.CompareTo(i1)));
     
        // sort the vertical cost in reverse order
        Array.Sort(Y, new Comparison(
                (i1, i2) => i2.CompareTo(i1)));
     
        // initialize current width as 1
        int hzntl = 1, vert = 1;
     
        // loop until one or both
        // cost array are processed
        int i = 0, j = 0;
        while (i < m && j < n)
        {
            if (X[i] > Y[j])
            {
                res += X[i] * vert;
     
                // increase current horizontal
                // part count by 1
                hzntl++;
                i++;
            }
            else
            {
                res += Y[j] * hzntl;
     
                // increase current vertical
                // part count by 1
                vert++;
                j++;
            }
        }
     
        // loop for horizontal array,
        // if remains
        int total = 0;
        while (i < m)
            total += X[i++];
        res += total * vert;
     
        // loop for vertical array,
        // if remains
        total = 0;
        while (j < n)
            total += Y[j++];
        res += total * hzntl;
     
        return res;
    }
     
    // Driver program
    public static void Main(String []arg)
    {
        int m = 6, n = 4;
        int []X = {2, 1, 3, 1, 4};
        int []Y = {4, 1, 2};
        Console.WriteLine(minimumCostOfBreaking(X, Y, m-1, n-1));
    }
}
 
// This code is contributed by Princi Singh


Javascript


输出:

42

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程