最大化切割段

Description:

描述:

In this article we are going to review classic dynamic programing problem which has been featured in interview rounds of amazon.

在本文中,我们将回顾在亚马逊的采访轮次中已经介绍的经典动态编程问题。

Problem statement:

问题陈述:

Given an integer N denoting the Length of a rod, one needs to cut the rod in such a way that the cut length of the rod segment each time is integer either x, y or z and after performing all cutting operation the total number of cut segments must be maximum. You need to find the maximum number of segments possible to cut.

给定一个表示杆长度的整数N ,则需要以这样一种方式切割杆,即杆段的切割长度每次都是xyz的整数,并且在执行所有切割操作后,切割的总数细分必须最大。 您需要找到可能要切割的最大段数。

Example:

例:

    Input1
    Rod length: 6
    Segment's length:
    x=3,y=2,z=1
    
    Output1
    Maximum number of cut segments: 6

    Input2
    Rod length: 5
    Segment's length:
    x=5,y= 3,z= 2
    
    Output2
    Maximum number of cut segments: 2

Example with explanation:

带有说明的示例:

    For the first example,
    Length of the rod is: 4
    Three cut segments’ length is 3, 2, 1 respectively. 
    To get maximum cuts we would cut in segments of length 
    1 which will have outcome 6.
    
    For the second example,
    Length of the rod is: 5
    Three cut segments’ length is 5, 3, 2 respectively. 
    To get maximum cuts we would cut in segments of 
    length 2 & length 3 which will have outcome 2. 

Solution Approach:

解决方法:

This problem can be solved recursively.

此问题可以递归解决。

    f(n) = number of cut segments for rod with length n
    f(n) = 1+maximum(f(n-x),f(n-y),f(n-z))

With base case,

在基本情况下

    f(negative number) = INT_MIN
    f(0) = 0

So, the recursive function definition would be:

因此,递归函数定义为:

Maximize the cut segments

Solving the above recursive function would give the result.

解决上述递归函数将得到结果。

The function is defined below,

该函数定义如下,

    Function cutTheRod(n):
	    If n<0
    	    return INT_MIN
	    If n==0
	        return 0;
	    return 1+maximum(f(n-x),f(n-y),f(n-z));
    End Function

If you draw any recursion tree, you will find many overlapping subproblems and hence we need to store them and use dynamic Programing to solve.

如果您绘制任何递归树,您会发现许多重叠的子问题,因此我们需要存储它们并使用动态编程来解决。

Before going to a dynamic programming solution, let’s talk about one observation. The thing is as we need to find the maximum number of cuts, we would like to use the minimum long segment as much as possible. It seems that greedy would have worked by choosing minimum long segments and then upgrading to other segments. If greedy works for a test case, the solution is guaranteed to be optimal. Earlier we have seen that greedy may not be optimal, but it’s not in this case. In this case greedy is optimal. The issue is greedy doesn’t work for all test cases. Think of a test case such that rod length is 9:

在使用动态编程解决方案之前,让我们谈谈一个观察。 事情是因为我们需要找到最大的切割数量,因此我们希望尽可能地使用最小的长段。 贪婪似乎可以通过选择最小的长段然后升级到其他段来起作用。 如果贪婪适用于测试用例,则可以保证解决方案是最佳的。 之前我们已经看到贪婪可能不是最佳选择,但在这种情况下并非如此。 在这种情况下,贪婪是最优的。 问题是贪心并不适用于所有测试用例。 考虑一个测试用例,其杆长度为9:

And segment lengths are: 5, 3, 2

段长度为:5、3、2

Greedy would have cut 4 segments of length 4 and then fails eventually as no segment of length 1. That’s why we need DP, but there is one greedy technique that can be added along to optimize. Since, we need to find maximum cuts, find out the minimum segment and check whether the rod length is divisible by the minimum length or not. If it’s divisible that ensures that rod length/minimum cut length is the maximum number of cut segments. You can check for example 1 there are 4 cut segments, which is rod length(4)/ minimum segment length(1) since rod length was divisible by minimum segment length.

贪婪本来会切掉4个长度为4的片段,然后由于没有长度为1的片段而最终失败。这就是为什么我们需要DP的原因,但是可以添加一种贪婪技术来进行优化。 因为,我们需要找到最大的切口,找出最小的段,并检查杆的长度是否可被最小长度整除。 如果可以整除,则确保杆长度/最小切割长度为最大切割段数。 例如,您可以检查1个有4个切割段,这是杆长度(4)/最小段长度(1),因为杆长度可以被最小段长度整除。

The Dynamic programing solution can be found below:

动态编程解决方案可以在下面找到:

  1. Initialize dp[n+1] in the following way.

    通过以下方式初始化dp [n + 1]。

        dp[0]=0
        for  i=1 to n
        dp[i]=INT_MIN
    
    
  2. Fill the table

    填表

        for i=1 to i++)
    	    if(i-x>=0 && dp[i]<1+dp[i-x])
    		    dp[i]=1+dp[i-x];
    
    	    if(i-y>=0 && dp[i]<1+dp[i-y])
    		    dp[i]=1+dp[i-y];
    
    	    if(i-z>=0 && dp[i]<1+dp[i-z])
    		    dp[i]=1+dp[i-z];
        end for
    
    
  3.     If dp[n]<=0
            Cutting not possible
        Else
            That's the result.
    
    

C++ Implementation:

C ++实现:

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

int cuttingrod(int n, int x, int y, int z)
{
    int minimum;
    if (x < y && x < z)
        minimum = x;
    if (y < x && y < z)
        minimum = y;
    if (z < y && z < x)
        minimum = z;

    if (minimum != 0 && n % minimum == 0)
        return (n / minimum);

    int dp[n + 1];
    for (int i = 1; i <= n; i++)
        dp[i] = INT_MIN;
    dp[0] = 0;
    for (int i = 1; i <= n; i++) {

        if (i - x >= 0 && dp[i] < 1 + dp[i - x]) {
            dp[i] = 1 + dp[i - x];
        }
        if (i - y >= 0 && dp[i] < 1 + dp[i - y]) {
            dp[i] = 1 + dp[i - y];
        }
        if (i - z >= 0 && dp[i] < 1 + dp[i - z]) {
            dp[i] = 1 + dp[i - z];
        }
    }
    return dp[n];
}

int main()
{
    int t, n, x, y, z;

    cout << "Original rod length:\n";
    cin >> n;
    cout << "First cut segment length,x:\n";
    cin >> x;
    cout << "Second cut segment length,y:\n";
    cin >> y;
    cout << "Third cut segment length,z:\n";
    cin >> z;

    int ans = cuttingrod(n, x, y, z);
    if (ans > 0)
        cout << "Max number of cut segments: " << ans << endl;
    else
        cout << "Can't be cut down\n";

    return 0;
}

Output

输出量

RUN 1:
Original rod length:
6
First cut segment length,x:
3 2 1
Second cut segment length,y:
Third cut segment length,z:
Max number of cut segments: 6

RUN 2:
Original rod length:
17
First cut segment length,x:
11
Second cut segment length,y:
13
Third cut segment length,z:
9
Can't be cut down


翻译自: https://www.includehelp.com/icp/maximize-the-cut-segments.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值