我的dp方法在哪里出错? https://www.spoj.com/problems/AE00/

时间:2019-04-04 10:22:07

标签: algorithm dynamic-programming

问题:

  

Byteman的第1面有N个正方形的集合。有多少个不同   他可以使用这些正方形形成矩形吗?

     

如果两个矩形都不能旋转,则认为它们是不同的   并获得第二个。在矩形构造过程中,   字节曼既不能使正方形变形,也不能在任何正方形上放置任何正方形   其他的。

     

输入标准输入的第一行也是唯一一行   整数N(1 <= N <= 10000)。

     

输出标准输出的第一行和唯一行应包含一个   一个整数,等于等于的不同矩形的数量   字节曼可以使用他的正方形来形成。

     

示例对于输入数据:6

     

正确的结果是:8

我的解决方案:

public class Rectangles {
    public void solve(int testNumber, Reader in, OutputWriter out) {
        try {
            while(true) {
                int N = in.ni();
                out.printLine(result(N));
            }
        } catch (Exception ee) { }
    }

    private long result(int n) {
        long[] res = new long[n+2];
        res[0] = 0;
        res[1] = 1;
        res[2] = 2;
        for(int i=3;i<=n;i++) {
            if(i%2 == 0) {
                res[i] = 3 + res[i-2];
            } else {
                res[i] = 1 + res[i-1];
            }
        }
        return res[n];
    }
}

我的DP方法:

For 0 squares: Result is 0
For 1 square: Result is 1: f(1) = 1
For 2 squares: Result is 2 : f(2) = 2
Now for f(3) = f(2) + 1 more square
With 1 more square we can only place it horizontally and hence 
f(3) = f(2)+1, generalizing, when n is ODD : f(n) = f(n-1) + 1
when n is EVEN: we use two squares which can make up to 3 rectangles, two horizontally([SQ] & [SQ][SQ]) plus one on top of the other, so total 3 possibilities, and hence f(n) when n is EVEN: f(n) = f(n-2) + 3.

3 个答案:

答案 0 :(得分:1)

并非所有矩形都是通过在现有矩形上添加一个正方形而获得的。

例如,如果N = 9,则矩形之一是3x3。您的DP方法找不到它。换句话说,就是f(9)> f(8)+ 1。

答案 1 :(得分:1)

对于给定的N,所有可能的不同矩形是:

  1x1 1x2 1x3 1x4 ... 1x[N/1]
      2x2 2x3 2x4 ... 2x[N/2] // 2x1 is equals to 1x2 
          3x3 3x4 ... 3x[N/3] // 3x1 and 3x2 are equal to 1x3 and 2x3
                  ... 
                      Mx[N/M]   

其中[...]表示整数部分floor),换句话说,[N/M]整数除。由于N不太大,我们可以循环

C#代码:

private static int Solution(int value) {
  int result = 0;

  for (int i = 1; ; ++i) {
    int upTo = value / i;

    if (i > upTo)
      return result;

    result += (upTo - i + 1);
  }
}

演示:

  int[] tests = new int[] {
    0,
    1,
    6,
    9,
    10000,
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,5} -> {Solution(test),5}"));

  Console.Write(report);

结果:

    0 ->     0
    1 ->     1
    6 ->     8
    9 ->    13
10000 -> 46884

答案 2 :(得分:0)

我建议考虑有多少个较小的(!)边为长度 x 的矩形。然后遍历 x 的所有可能值,并将其求和。 伪代码:

result = 0
for x in 1 .. floor(sqrt(n)):
  result += number_of_rectangles_with_smaller_side(x)

我认为number_of_rectangles_with_smaller_side(x)floor(n / x) - x + 1,但您应该仔细检查;-)

相关问题