鉴于木板由M X N木制方块组成,我们需要找到将木板打成方形木块的最低成本。
我们可以沿水平和垂直线切割电路板,每次切割将电路板分成较小的部分。每块板的切割成本取决于切割是沿水平线还是垂直线进行。
让我们用沿x [1],x [2],...,x [n-1]的连续垂直线和y [1],y [2],...的水平线切割它的成本。 ,y [m-1]。如果削减(成本c)并且它通过n个段,那么这个削减的总成本将为n * c。
将整块板切割成单个正方形的成本是用于将整个板切割成尺寸为1x1的方形木块的连续切割成本的总和。
将整个木板分成1x1大小的最小成本是什么。
示例:我们采取6 * 4网格。
让沿着行划分成本如下:[2 1 3 1 4]
按照以下方式削减柱成本:[4 1 2]
这里的答案是42
我们应该按顺序使用y5,x1,y3,y1,x3,y2,y4和x2开始切割。第一次切割将是水平的,其中cost = y5 = 4.接下来我们将使用x1进行垂直切割。由于此切割通过两个段(由先前的垂直切割创建),因此总成本将为2 * x1 = 2 * 4。类似地,下一个水平切割(y3)将通过两个段并且将花费2 * y3 = 2 * 3。我们可以采取类似的方式进行,总成本为4 + 4 * 2 + 3 * 2 + 2 * 2 + 2 * 4 + 1 * 3 + 1 * 3 + 1 * 6 = 42。
我的方法:检查从第1行和第2行之间的切割开始的每次切割,然后等等。但显然效率太低。那么如何解决这个问题呢?
答案 0 :(得分:18)
分割线的选择应按递减的成本顺序进行,以实现最低的总成本。
<强>证明:强>
任何“错误”排序的切割序列必须具有2个连续切割C1和C2,其成本为c1和c2,使得c1 另一方面,如果C1是垂直的而C2是水平的(不失一般性),那么我们可以如下检查它。设V0为施加C1之前的垂直片段数,H0为C1之前的水平片段数。 第一个表达式减去第二个表达式给出了c2-c1,它是正的。换句话说,交换C1和C2可以降低成本。 结论:使用一系列交换,任何非有序序列都可以转换为有序序列,这样总成本只能降低。这样就完成了最优性证明。 注意:如果多次削减成本相同,其内部订购根本不会影响总成本,如上面的计算所示。
答案 1 :(得分:3)
这个问题可以通过贪婪算法来解决。
仅有1条规则: - 按递减顺序选择切割成本,如果两个或更多成本相等,请选择任意一个。 这是python解决方案: -
M, N = map(int, raw_input().strip().split(' '))
Y = map(int, raw_input().strip().split(' '))
X = map(int, raw_input().strip().split(' '))
Y.sort(reverse=True)
X.sort(reverse=True)
y_cut = x_cut = 1 #To count the number of segments
cost = i = j = 0
while i < X.__len__() and j < Y.__len__():
if X[i] >= Y[j]:
x_cut = x_cut + 1
cost = cost + (X[i]*y_cut)
i = i+1
else:
y_cut = y_cut + 1
cost = cost + (Y[j]*x_cut)
j = j+1
while i < X.__len__():
cost = cost + (X[i]*y_cut)
i = i+1
while j < Y.__len__():
cost = cost + (Y[j]*x_cut)
j = j+1
print cost
答案 2 :(得分:1)
虽然问题已经得到解答,但我写这篇文章是为了提供一个非正式的,可能是直观的解释:
我们必须进行(n-1)*(m-1)次切割,所以我们只需要决定首先选择哪种切割。
让我们说我们必须在成本c1和c2的两个削减C1和C2之间进行选择。我们说c1> c2。让整个事件的总电流成本用C
表示如果我们在此步骤之后选择C1,它将至少添加(取决于您是否在下一步中添加它)c1到整个成本,C。 如果我们在这个步骤之后选择C2,它将至少将c2添加到整个成本,C。
所以我们可以说我们现在可以贪婪地选择C1,因为以后选择它会比以后选择C2更糟糕。
因此,我们选择降低成本的顺序,而不管切割的类型(水平,垂直)。
答案 3 :(得分:0)
只需选择降低成本的切割线,这里是c ++中的代码
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
long int t;
cin >> t;
while(t--){
long long int m,n,*x,*y,i,j,sum,cx,cy,modu = 1000000007;
cin >> m >> n;
x = new long long int[m-1];
y = new long long int[n-1];
for(i=0;i<m-1;i++)
cin >> x[i];
for(i=0;i<n-1;i++)
cin >> y[i];
sort(y,y+n-1);
sort(x,x+m-1);
i=m-1-1;sum=0;j=n-1-1;cx = 1;cy =1;
while(i>=0 && j >=0){
if(x[i] > y[j]){
sum += (x[i]*cy)%modu;
cx++;
i--;
}
else{
sum += (y[j]*cx)%modu;
cy++;
j--;
}
}
while(i>=0){
sum += (x[i]*cy)%modu;
i--;
}
while(j>=0){
sum += (y[j]*cx)%modu;
j--;
}
cout << sum%modu << endl;
}
return 0;
}
答案 4 :(得分:0)
这是我在Python 2中的贪婪算法。
<强>代码强>
M,N = [int(x) for x in raw_input().split()]
CY = sorted([int(x) for x in raw_input().split()], reverse=True)
CX = sorted([int(x) for x in raw_input().split()], reverse=True)
nx = 1
ny = 1
minC = 0
i = 0
j = 0
total = M - 1 + N - 1
for _ in range(0,total):
#j == N - 1 to check if CX is exhausted
if (j == N - 1 or (i != M -1 and CY[i] > CX[j])):
minC += CY[i]*nx
ny += 1
i += 1
else:
minC += CX[j]*ny
nx += 1
j += 1
print minC%(1000000000+7)
答案 5 :(得分:-2)
嗯,这似乎很简单。因此,您需要进行所有削减并最大限度地减少最昂贵的削减数量,您只需按成本订购即可。
虽然有一个问题 - 如果您的削减价格相同,那么您需要对它们进行分组。假设您必须进行5次切割,每种价格为6,列数为4,行数为2,未切割。如果您先裁减2行,则费用为2 * 6 + 4 * 3 * 6 = 14 * 6
。如果您以其他方式执行此操作,则会获得4 * 6 + 2 * 4 * 6 = 12 * 6
。
规则首先是高价切割,首先沿轴线进行大多数切割。
编辑:要跟踪您拥有的细分数量,您需要跟踪对其他轴进行的剪切。 o如果您对行进行了3
切割,则切割列将需要3 + 1
次切割。如果您已经剪切了5
列和3
行,则切割另一行将始终必须遍历每个列切割行,这意味着您必须剪切5 + 1
次。
编辑2:由于我的示例不正确,这就是使用来自问题的情况的样子:
cut_x = [2, 1, 3, 1, 4]
cut_y = [4, 1, 2]
list_of_cuts_grouped_by_cost_descending = [[x5, y1], [x3], [x1, y3], [x2, y2, x4]]
cut_groups_ordered_by_most_cut_axis = [[x5, y1], [x3], [x1, y3], [x2, x4, y2]]
return cut_groups_ordered_by_most_cut_axis.flatten