给定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.任何其他替代解决方案。
答案 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 + by
,a
受b
和a<=m
限制。
你可以通过
来完成计算x和y的最大公约数b<=n
。
如果d = GCD(x,y)
不是z
的倍数,则无法解决。
如果d
可被z
整除,请计算d
,z' = z / d
和x' = x / d
。
使用Extended Euclidean Algorithm({基本上是一个循环并在O中运行(log(max(z, x,y)))。
将y' = y / d
和z' = a'x' + b'y'
乘以a'
b'
和a
检查解决方案是否满足约束b
和a'
。
答案 3 :(得分:0)
您的问题是缩小为a
和b
,z=ax+by
,a<=m
和b<=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;
}