【问题标题】:How can I maximise the number of ribbon piece for a ribbon of given length n?对于给定长度 n 的色带,如何最大化色带片的数量?
【发布时间】:2015-06-03 12:45:48
【问题描述】:

我有一条丝带,它的长度是 n。我想以满足以下两个条件的方式剪彩:

1. After the cutting each ribbon piece should have length a, b or c.
2. After the cutting the number of ribbon pieces should be maximum.

求出所需切割后的最大件数。

输入格式为n,a,b,c,其中n 是色带的原始长度,a、b、c 是所需的色带长度。

For eg: I/P = 5 5 3 2
O/P = 2

现在,我能够意识到这应该遵循 DP 解决方案。一维 DP,其中 dp[n] 表示长度为 n 的色带的最大路数。

现在,我不确定递归关系是否是这种形式,

dp[n] = dp[n-a] + a;
dp[n] = dp[n-b] + b;
dp[n] = dp[n-c] + c;

这是正确的还是有其他方法?

编辑:根据第一篇文章实现:

#include <iostream>
#include <cmath>
using namespace std;

int dp[100000];
int maxi (int a,int b,int c);
int main (void)
{
    int n,a,b,c;
    cin>>n>>a>>b>>c;
    for (int i = 0; i <= n; i++)
    {
        if ( i == 0 )
            dp[i] = 0;
        else
            dp[i] = maxi(dp[i-a],dp[i-b],dp[i-c])+1;
    }
    cout<<dp[n]<<"\n";
    return 0;
}

int maxi (int a,int b,int c)
{
    int ret;
    if ( a > b )
        ret = a;
    else 
        ret = b;
    if ( ret < c )
        ret = c;
    return ret;
}

【问题讨论】:

  • 不,不正确。如何为 dp[n] 分配三个不同的值?
  • 找到 min(a,b,c) 并​​切割所有相同长度的部分?
  • 不能是dp[n] = dp[n-a] + dp[n-b] + dp[n-c] + 3 之类的吗? (我可能肯定是错的,但只是问)。
  • @zubergu,我想到了。但是假设色带长度为5min = 2,其中a=2, b=3, c=4 切割后,我们将得到长度为2 2 1 的片段。但是1 作为长度是不可接受的。因此我们不能这样做。
  • 你越来越近了,但事实并非如此。你也许可以想想你给出的例子:dp[1] = 0, dp[2] = 1, dp[3] = 1, 你将如何计算 dp[5] ?

标签: algorithm


【解决方案1】:
if n < 0:
    dp[n] = -infinity
if n == 0:
    dp[n] = 0
if n > 0:
    dp[n] = 1 + max(dp[n-a], dp[n-b], dp[n-c])

【讨论】:

  • 所以,我实现了上面的逻辑。但是,当我在在线评委中提交此内容时,它对输入的4000 1 2 3 给出了错误的答案。执行中有什么问题吗?我已经在原帖中添加了实现。
  • 您似乎没有与我的第一个 dp[n] = -infinity 块对应的任何代码。这对于检测色带无法均匀切割的情况是必要的。
  • 我更正了 max 函数。但是,@kevin,当 n
  • 抱歉,我对正确设计 C 代码知之甚少。如果这是 Python,你可以只写一个记忆递归函数,你甚至根本不需要 dp 集合。
  • @Kevin,我只有一个疑问。你已经写了if n &lt; 0, dp[n] = -infinity,这里如果n &lt; 0,那么你如何访问具有该索引的数组?
【解决方案2】:
for (int i = 0; i <= n; i++)
    {
        if (i == 0)
            dp[i] = 0;
        else {
            int A = (i-a>=0) ? dp[i-a] : -n-1;
            int B = (i-b>=0) ? dp[i-b] : -n-1;
            int C = (i-c>=0) ? dp[i-c] : -n-1;
            dp[i] = maxi(A,B,C)+1;
        }
    }

【讨论】:

  • 只是一个小疑问,如果我可以取任何负值,对吗?代替-n-1,对吧?
  • 不确定。应该是-无穷大,-n-1当然就够了。但我不确定是否只取任何负值。你为什么不坚持使用 -n-1 呢
  • 是的,这行得通,但我问你是否有什么特殊原因让你接受这个值。
  • 您应该为对您有帮助的答案投票并验证最好的答案(在本例中为 Kevin 的答案)。对于这个问题......以及您之前提出的其他问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-15
  • 2020-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
相关资源
最近更新 更多