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

📅  最后修改于: 2021-04-29 08:32:10             🧑  作者: Mango

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

木板对于上面板,切成正方形的最佳方法是:在上述情况下,最低总成本是42。使用以下步骤进行评估。初始值:Total_cost = 0 Total_cost = Total_cost + edge_cost * total_pieces成本4水平切割成本= 0 + 4 * 1 = 4成本4垂直切割成本= 4 + 4 * 2 = 12成本3垂直切割成本= 12 + 3 * 2 = 18成本2水平切割成本= 18 + 2 * 3 = 24成本2垂直切割成本= 24 + 2 * 3 = 30成本1水平切割成本= 30 + 1 * 4 = 34成本1垂直切割成本= 34 +1 * 4 = 38成本1垂直切割成本= 38 + 1 * 4 = 42

这个问题可以用贪婪的方法解决,如果总成本用S表示,则S = a1w1 + a2w2…+ akwk,其中wi是某条切边的成本,ai是相应的系数,系数ai由总和决定。在切割过程结束时,我们使用wi进行竞争的切割次数。注意,系数的总和始终是恒定的,因此我们希望找到a可获得的a的分布,以使S最小。为此,我们尽早在最高成本的边上进行切割,这将达到最佳S。如果遇到多个成本相同的边,我们可以先切割其中的任何一条。
下面是使用上述方法的解决方案,首先我们以相反的顺序对切边成本进行排序,然后将它们从较高的成本循环到较低的成本,以构建我们的解决方案。每次我们选择一条边时,对应零件的数量都会增加1,每次乘以相应的边切割成本。
请注意,下面使用了sort方法,将biger()作为第三个参数发送给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 untill 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 untill 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 untill 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 untill 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


输出:

42