【问题标题】:Create 2 pillars of equal height from an array of bricks从一组砖块中创建 2 个等高的柱子
【发布时间】:2017-09-15 01:06:52
【问题描述】:

问题陈述:

有 N 块积木 (a1, a2, ...., aN)。每块砖的长度为 L1, L2, ...., LN)。使用提供的砖块制作 2 个最高的平行柱子(相同长度的柱子)。

约束:

  1. 有 N 块砖。 5
  2. 每块砖的长度。 1
  3. 砖块长度的总和

砖块的长度没有按尺寸顺序给出。可能有多个具有相同长度的砖块。并非所有的砖都必须用来制作柱子。

例子:

第一个例子-

N = 5
2、3、4、1、6

可能的组合:
(2, 6) 和 (3, 4, 1)

答案:8

我的方法:

找到 2 个平行柱子的最大可能长度,即。地板(N / 2)。然后,使用 DP 找到所有可能使用所有积木的总和长度。从可能的最高总和

上述方法的问题在于它只检查元素的一个子集以形成所需的总和。应该检查可以形成所需总和的所有可能子集,然后对于这些子集中的每一个,使用剩余的元素检查是否可以形成相同的所需总和。问题是在我目前的方法中实现这一点。

第二个例子-

N = 6
3、2、6、4、7、1

可能的组合:
(3, 2, 6) 和 (7, 4)

答案:11

我的代码中的问题可能出现在这种情况下,具体取决于元素(砖块长度)作为输入的顺序。第一个集合可能是使用元素 (3, 7, 1) = 11 形成的,但第二个集合 (2, 6, 4) 不能形成 sum = 11。因此,我的代码开始寻找下一个可能的最大值总和。 10 错了。

有人可以建议我目前的方法更好的方法或可能的改进吗?

【问题讨论】:

    标签: algorithm graph tree dynamic-programming backtracking


    【解决方案1】:

    我认为您可以通过动态编程来解决这个问题,其中对于每一对 (x, y),您可以计算出是否可以使用与目前考虑的砖块不同的砖块来构建长度为 x 和 y 的柱子。

    依次考虑每块砖。一开始只有 (0, 0) 是可能的。当你看到一块长度为 L 的砖块时,对于每个可能的柱子 (x, y) 都有三个后代 - (x, y)(忽略砖块),(x + L, y)(使用第一根柱子上的砖块) , 和 (x, y + L)(使用第二根柱子上的砖块)。

    因此,在您考虑了所有积木之后,您将获得一长串可能的配对,您只需选择具有相同长度且尽可能长的两根柱子的配对即可。只要不存在太多不同的对(您可以从列表中删除任何重复项),这将是实用的。

    假设砖块的长度是整数并且最大柱子长度是 1000,那么只有 1001 * 1001 个可能的对,所以这应该是实用的,事实上,如果你通过一个大小为 [ 的数组来存储对,这可能是最简单的。 1001, 1001] 并将条目 [x, y] 设置为 1 如果对 (x, y) 是可能的,否则设置为 0。

    对于示例的前几个步骤,可达状态是

    (0,0) 什么都不考虑

    (0,3) (3,0) (0,0) 考虑 3

    (0,5) (2,3) (0,3) (5,0) (3,0) (0,2) (2,0) (0,0) 考虑到 3 和 2

    可达状态的数量起初增长得非常快,但由于我们只考虑 0..1000 的值,而且我们只关心数组是否可达,我们可以使用维度为 1001x1001 的布尔数组来维护它们

    【讨论】:

    • 我添加了一个示例来尝试澄清事情。因为我们只关心状态是否可达,我们可以将其存储为大小为 1001x1001 的布尔数组。这不像树那么复杂,因为可以有许多通往同一状态的路径。例如,如果我们有三个大小为 1 的砖块,我们得到 (0,0) -> (0,1) (1,0) (0,0) -> (0,2) (1,1) (2,0 ) (0, 1) (1, 0) (0,0) -> (0,3) (1,2) (2,1) (3,0) (2,0) (1,1) (0 ,2) (1,0) (0, 1) (0,0) 实际上在第 n 步有 [(n+1)(n+2)]/2 对从 n=0 开始计数,直到我们得到删除值 > 1000 的状态
    • 你可以使用队列,但你需要一些方法来检测队列中的重复项,这样字节或位数组可能会更容易,因为你可以在那里设置元素,而重复项你只需覆盖位置你已经设置好了。请注意,您需要保留旧元素,因此如果您从 (x, y) 开始,您应该在下一阶段拥有 (x, y) 和 (x+L, y) 和 (x, y+L)。这说明了在最佳解决方案中可能根本不会使用 L。
    • 您给出的示例说明了为什么您应该将 (0,0) 留在队列中(或设置在数组中)。如果您在处理 1 后将其保留,则可以在处理 5 后生成 (5, 0),这会导致 (5, 3) 然后 (5,5) 被认为是最佳答案。
    • 我假设长度是整数,问题是砖块长度的总和
    • @shashank 一旦你有了一对,例如 (0,4),你永远不会丢弃它,但你永远不需要每对的一个以上的副本——如果你使用建议的布尔数组并将元素设置为 true 以指示现在可以配对 - 将元素设置为 true 两次与设置为 true 一次相同。
    【解决方案2】:

    嗯,这个问题可以简单地使用递归来解决。但是对于较大的 n 值,它不会是有效的。这是我的代码

    #include <iostream>
    using namespace std;
    
    void solve(int a[], int vis[], int p1, int p2, int n, int &ans){
        if(p1 == p2){
    
            if(p1 > ans){
                ans = p1;
            }
        }
    
        for(int i=0 ; i<n ; ++i){
    
            if(vis[i] == 0){
                vis[i] = 1;
                solve(a, vis, p1 + a[i], p2, n, ans);
                solve(a, vis, p1, p2 + a[i], n, ans);
                vis[i] = 0;
            }
        }
    }
    int main(){
    
        int n;
        cin>>n;
        int a[n];
    
        for(int i=0 ; i<n ; ++i){
            cin>>a[i];
        }
    
        int vis[n] = {0};
        int ans = -1;
        solve(a,vis,0,0,n,ans);
    
        cout<<ans;
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      最近我在准备三星能力测试时尝试解决这个问题。我构建了解决方案,这可能会帮助你们练习。感谢https://stackoverflow.com/users/240457/mcdowella,我能够使用他的策略解决这个问题。

      public class Pillars {
          public static int h=0,mh=0; 
          public static void main(String[] args)  {   
              java.util.Scanner scan = new java.util.Scanner (System.in);
              int n = scan.nextInt();
              int a[]=new int[n];     
              for(int i=0;i<n;i++)
              {
                  a[i]=scan.nextInt();
                  mh+=a[i];
              }
              mh/=2;// the height of the two pillars is the total, then single pillar can't be more than half of total 
              maxHeight(0,0,a,0);
              // if no pillars can be built using the data, this print statement is executed
              System.out.println("Maximum Height Formed with the given Data "+h);     
          }
      
          public static void maxHeight(int x,int y,int a[],int i)
          {
              if(x==y && x!=0 && x>h)// whether the heights formed are equal or not 
              {
                  h=x;
                  if(h==mh) // if equal then print and exit the program
                  {
                      System.out.println("Maximum Height Formed with the given Data "+h);
                      System.exit(0);
                  }
              }
              if(i<a.length )
              {
                  maxHeight(x+a[i],y,a,i+1);
                  maxHeight(x,y+a[i],a,i+1);          
              }       
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        相关资源
        最近更新 更多