【问题标题】:Find the minimum number of MS Paint operations to fill a rectangle找到填充矩形的最小 MS Paint 操作数
【发布时间】:2015-10-21 01:45:26
【问题描述】:

我在比赛的某个地方发现了这个问题,但还没有想出解决方案。

我可以在另一个地方“选择”、“复制”、“插入”和“移动”一个数字 屏幕上。最初我有一个大小为 1x1 的矩形。最少的是什么 我必须做的这些操作的数量来构建另一个 矩形,大小为 AxB。

这是我的错误代码:

#include <iostream>
#include <cmath>
#define size 1002
using namespace std;

int main()
{
    int painta[size];
    int paintb[size];
    int i,j,a,b,temp;

    cin >> a >> b;
    if (a>b)
    {
        temp=a;
        a=b;
        b=temp;
    }

    painta[1]=4;
    for (i=2; i<=a; i++)
        painta[i]=painta[i-1]+2;

    for (i=2; i<=a; i++)
    {
        painta[2*i]=min(painta[i]+4,painta[2*i]);
        for (j=3*i; j<=a; j+=i)
        {
            painta[j]=min(painta[j-i]+2,painta[j]);
        }
    }

    paintb[1]=painta[a];
    paintb[2]=paintb[1]+4;

    for (i=3; i<=b; i++)
        paintb[i]=paintb[i-1]+2;

    for (i=2; i<=b; i++)
    {
        paintb[2*i] = min(paintb[i]+4,paintb[2*i]);
        for (j=3*i; j<=b; j+=i)
        {
            paintb[j]=min(paintb[j-i]+2,paintb[j]);
        }
    }
    cout << paintb[b] << endl;
    return 0;
}

这里是链接:http://www.e-olymp.com/en/problems/18

【问题讨论】:

  • 请用简单的英语解释您的算法,以传达您认为它应该起作用的直觉。另外,请注明问题的根源,以便我们向自己保证这不是现场比赛的一部分,以便我们有机会尝试自己的解决方案
  • @Niklas B 我已经编辑了问题。
  • 什么是“移动”操作?
  • 试试测试用例1 2。也可以考虑1 51 9

标签: c++ algorithm dynamic-programming


【解决方案1】:

您的方法还可以,尽管您犯了一些实现错误,您可以通过检查一些小测试用例来发现这些错误。

例如,一个失败的测试用例是1 2,您的程序给出的答案是8,尽管6 是正确的。这是因为您的算法应该使用 a &gt; b 而不是 b &gt; a

-    if (a>b)
+    if (a<b)

现在我们仍然遇到像1 7 这样的测试用例的问题。正确答案是 14,但您的程序回答 16。原因是您不允许重叠插入:从大小为 1x2 的矩形开始,我们可以使用序列选择、复制、插入+移动、插入+移动,插入+移动,插入+移动得到一个大小为 1x7 的矩形。考虑到这一点,程序只会稍微复杂一点:

@@ -24,9 +24,10 @@
     for (i=2; i<=a; i++)
     {
         painta[2*i]=min(painta[i]+4,painta[2*i]);
-        for (j=3*i; j<=a; j+=i)
+        for (j=2*i+1; j<=a; j++)
         {
-            painta[j]=min(painta[j-i]+2,painta[j]);
+            int steps = (j - i - 1) / i;
+            painta[j]=min(painta[2*i]+2*steps,painta[j]);
         }
     }

@@ -39,9 +40,10 @@
     for (i=2; i<=b; i++)
     {
         paintb[2*i] = min(paintb[i]+4,paintb[2*i]);
-        for (j=3*i; j<=b; j+=i)
+        for (j=2*i+1; j<=b; j++)
         {
-            paintb[j]=min(paintb[j-i]+2,paintb[j]);
+            int steps = (j - i - 1) / i;
+            paintb[j]=min(paintb[2*i]+2*steps,paintb[j]);
         }
     }

现在这里仍然有一个小溢出,这可能会导致程序因大量输入而崩溃:您正在循环内访问painta[2*i]paintb[2*i]i 可以最大为1000,但数组只有1002 的大小。很容易修复:

@@ -5,12 +5,12 @@

 int main()
 {
-    int painta[size];
-    int paintb[size];
+    int painta[size*2];
+    int paintb[size*2];
     int i,j,a,b,temp;

瞧,它通过了所有的测试用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    相关资源
    最近更新 更多