给定一块长 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 现场工作专业课程和学生竞争性编程现场课程。