给定x英寸的砖块和y英寸的n块砖,使用给定砖块的组合创建z英寸的行

时间:2015-05-28 21:33:19

标签: c++ for-loop

给定m个小砖块(每个x英寸长)和n个大砖块(每个y英寸长),我们想要创建一个行z英寸长,使用小砖和大砖的组合。编写程序以验证是否可以创建这样的砖块行。

范例 -

输入:我们有4(m)个小砖,每个3英寸(x)长,3(n)个大砖,每个长4英寸(y)。我们需要创建长度为14(z)英寸的行。

输出:是

输入:我们有2(m)个小砖,每个2英寸(x)长,2(n)个大砖,每个5英寸(y)长。我们需要创建长度为6(z)英寸的行。

输出:否(没有砖块的组合会形成6英寸长的墙壁。)

这是我在面试过程中被问到的一个问题。我在C ++中编写了以下代码

#include <iostream>
using namespace std;
int main()
{ int m,x,n,y,z;
  int small=0, large=0, sum=0;
  cout<<"Enter values : ";
  cin>>m>>x>>n>>y>>z;
  int i=0,j=0,flag=0;
  for(i=0;i<m;i++)
    {   small=small+x;
        for(j=0;j<=n;j++)
            {   large=large+y;
                sum=small+large;
                if(sum==z || sum==small || sum==large)
                {
                cout<<"\nYes. Combination Possible";
                flag=1;
                }
                else if(sum>z && large>z)
                break;  
            }
        large=0;
    }
if(flag==0)
cout<<"\nNo. Not possible";
return 0;
}

如何使用单个循环或者甚至没有循环来解决这个问题?

注意:不允许使用解Mx + Ny = Z.任何其他替代解决方案。

5 个答案:

答案 0 :(得分:1)

你基本上都在尝试所有组合,当你找到一个有效的组合时,你甚至都没有停下来,你只是继续尝试它们。这当然可以改进:当你设置break;,然后在外部循环flag = 1;中时,我会1)if (flag == 1) break;,这样你就可以从两个循环中断,或者2)使用{ {1}}跳到循环的末尾(但这在面试中非常危险,因为你可能会发现有人讨厌goto ......),或3)直接goto

无论如何,我认为他们希望你实现一些branch-and-bound算法。例如,在您的方法中,您尝试从小的方法开始,然后尝试添加长的方法。假设通过采用cout << "Yes" << endl; exit(0);小的那些你已经超越i:是否有意义尝试采用0,1,2,......,z长砖?你已经知道你走得太远了。如果您从n开始并且已经增加,并且对于给定的i=0, j=0,您已经超越了z,那么您确定没有解决方案,并且您可以i。或者,假设对于当前cout << "No" << endl; exit(0);你不超过i,那么你进入内循环并开始添加长砖。如果在某个时刻你超越z,尝试添加更多砖块是否有意义?显然不是,你从内循环中更好z并再试一次小砖。换句话说:每当你确定你走得太远时,停下来。这意味着对于当前分支,您的下限高于您必须达到的值,也就是说,必须丢弃分支,因为它无法为您提供解决方案。然后,直接退出(如果在第一种情况下,您确定没有其他分支可以带您到解决方案)或者转到下一个分支。

您也可以采取相反的做法:如果,对于break的当前值,您会看到即使通过获取所有i长砖,您也无法到达n,这意味着尝试内循环是浪费时间,并且您可以从外循环z到下一次迭代,其中continue;增加。但是这需要一些数学(可以完成i),考虑到你给出的限制,可能不允许这样做。无论如何,这对应于检查您的上限是否太低。如果是,请跳过此分支继续。

我认为没有一个单循环的解决方案。如果你被迫使用一定数量的积木,让我们说10,你可以从10个小积木开始,检查,如果你还没有达到if (i*x + n*y < z),你可以换掉一小块一个长的一个,因此尝试:0和10,1和9,2和8,依此类推,直到10和0.这将是一个单循环。但是,没有办法事先知道你需要的砖块数量。我能想到的所有捷径都需要解决一些像z这样的方程式,这是不被接受的。

所以我选择了分支机构:不要尝试所有组合,而是尝试了解你是否在浪费时间,在这种情况下继续前进。

答案 1 :(得分:1)

这是方法:

用大砖填满整行,不超过所需的长度z 现在检查剩余长度是否是小砖长度的倍数 如果是,我们有足够的小砖块,我们有答案 如果没有,移除一块大砖(只要剩下大块砖)并再次尝试添加小砖块。 如果小砖的数量不足以达到所需的长度,那么就完成了。

代码:

#include <iostream>

using namespace std;

int main () {
   int m;   // number of small bricks
   int x;   // length of small bricks
   int n;   // number of big bricks
   int y;   // length of big bricks
   int z;   // length of wall

   cout << "Enter values : ";
   cin >> m >> x >> n >> y >> z;
   int flag = 0;

   for (int numBig = min(z / y, n); numBig >= 0; numBig--) {
      int sum = numBig * y;
      if ((z - sum) % x == 0) {
         int numSmall = (z - (numBig * y)) / x;
         if (numSmall <= m) {
            cout << "Yes. Combination Possible" << endl;
            flag = 1;
            break;
         } else {
            break;   // not enough small bricks
         }
      }
   }

   if (flag == 0)
      cout << "No. Not possible" << endl;
   return 0;
}

答案 2 :(得分:1)

您的任务实际上是解决linear Diophantine equation形式的问题

Map[String,String]

此外,我们要查找的未知数z = ax + byaba<=m限制。

你可以通过

来完成
  1. 计算x和y的最大公约数b<=n

  2. 如果d = GCD(x,y)不是z的倍数,则无法解决。

  3. 如果d可被z整除,请计算dz' = z / dx' = x / d

  4. 使用Extended Euclidean Algorithm({基本上是一个循环并在O中运行(log(max(z, x,y)))。

  5. y' = y / dz' = a'x' + b'y'乘以a'

  6. ,以计算b'a
  7. 检查解决方案是否满足约束ba'

答案 3 :(得分:0)

您的问题是缩小为abz=ax+bya<=mb<=n。您可以使用仅a上的一个循环来解决它并解析z=ax+by的等式b,同时检查条件b<=n。这就是全部。

答案 4 :(得分:0)

    #include <iostream>

using namespace std;

int main()
{
   int m;   // number of small bricks
   int x;   // length of small bricks
   int n;   // number of big bricks
   int y;   // length of big bricks
   int z,z1,flag=0,flag1=0,m1,n1;   // length of wall
    cin>>m;
    cin>>x;
    cin>>n;
    cin>>y;
    cin>>z;
    z1=z;
    m1=m;n1=n;
    while(z>=0&&m>=0){
        if(z%x==0){
            if(m>=z/x){
                flag=1;
                break;
            }
        }
        if(z%y==0){
            if(n>=z/y){
                flag=1;
                break;
            }
        }
        z=z-x;
        m--;
    }
    while(z1>=0&&n1>=0){
        if(z1%x==0){
            if(m1>=z1/x){
                flag1=1;
                break;
            }
        }
        if(z1%y==0){
            if(n1>=z1/y){
                flag1=1;
                break;
            }
        }
        z1=z1-y;
        n1--;
    }
    if(flag1==1 || flag==1){
        cout<<"Possble";
    }
    else{
        cout<<"Not Possible";
    }
    return 0;
}