问题链接:https://projecteuler.net/problem=669
背景:我现在有2个已赋值的一维动态数组a和b,a是存放了N个斐波那契数,b使用了“next permutation”实现了1到N的全排列。
问题:如何找到b中的一组排列,这组排列的**每**相邻两项元素之和等于某一个斐波那契数(即等于a中某个元素),最后输出这组排列。
本人萌新,目前使用两层循环来实现。但是由于第二层循环的判断条件符合就输出了结果,从而导致多输出了许多不符合要求的排列。
do
{
for (long i = 2; i < n; i++)
{
for (long j = 0; j < n - 1; j++)
{
if ((b[j] + b[j + 1]) == a[i])
{
for (long k = 0; k < n; k++)
cout << b[k] << "\t";
cout <<"K"<< endl;
}
}
}
} while (next_permutation(b, b + n));
有两个疑问。
1.你的next_permutation(b, b + n)是如何实现的?是保存了每一种排列吗
2.要输出的排列是你全排列中的一组排列吗?
我说一下我的想法:在你的第二层循环里,判断条件符合时,continue,不符合就break,跳出第二层循环,进行下一组排列的比对判断。在第二层循环外面,判断j是否是最后一个元素下标,输出这组排列。
符合条件就输出的东西是不符合条件的?你想怎么改
do{
bool flag = true;
for (long j = 0; j < n - 1 && flag; j++){
bool fFlag = false;
for (long i = 2; i < n; i++) {
if ((b[j] + b[j + 1]) == a[i])
fFlag = true;
flag &= fFlag;
}
if(flag){
for (long k = 0; k < n; k++)
cout << b[k] << "\t";
cout <<"K"<< endl;
break; //如果想输出所有结果就注释掉这一行
}
} while (next_permutation(b, b + n));
问题在于你的判读输出上:
你当前代码所实现的是只要一个排列中含有一个符合条件的两个相邻组合就会输出这个排列,同时如果一个排列中含有多个符合条件的组合,还会重复输出该排列。
所以整体来两你的判断逻辑不对,缺少必要的中断条件。
具体思路如下:
遍历b的所有排列(第一层循环)
遍历一个排列中的相邻的两个元素
判断相邻元素的和是是否满足条件,如果满足,则继续判断下两个元素,如不满住,则该排列已经不符合条件,可以进行下一个排列的判断。
如果一个排列的所有的相邻元素都满足条件,那么就可以确定这个排列就是符合要求的一个排列,输出该排列,结束所有循环即可。
根据以上逻辑修改你打代码即可,如过有困哪,我再帮你写代码(最好你能自己实现,对裂解会有帮助)。
do
{
long j=0;
for (j= 0; j < n-1; j++)
{
long i=0;
for (i= 0; i < n ; i++)
{
if ((b[j] + b[j + 1]) != a[i])
{
break;
}
}
if(i!=n)
{
break;
}
}
if (j==n-1)
{
for (long k = 0; k < n; k++)
cout << b[k] << "\t";
cout <<"K"<< endl;
break;
}
} while (next_permutation(b, b + n));
你看看这样可以不:
添加一个函数,假设你的a是全局的,n也是全局的:
bool isExist(long n , long *a,long temp)
{
for (long i = 0; i < n; i++)
{
if(temp == a[i])
{
return true;
}
}
return false;
}
do
{
bool flag = true;
for (long j = 0; j < n - 1; j++)
{
if(!isExist(n,a,(b[j] + b[j + 1])))
{
flag = false;
break;
}
}
if(flag){
for (long k = 0; k < n; k++)
cout << b[k] << "\t";
cout <<"K"<< endl;
}
} while (next_permutation(b, b + n));
你的代码逻辑调整一下就可以了哈
do
{
// 初始化查找标记
bool flag = false;
// 遍历当前排列b[n]
for (long j = 0; j < n - 1; j++)
{
// 标记为从b[j]元素开始,重新查找
flag = false;
// 遍历斐波那契数a[n]
for (long i = 2; i < n; i++)
{
// 排列中相邻两项元素之和等于某一个斐波那契数
if ((b[j] + b[j + 1]) == a[i])
{
// 标记为查找到匹配项
flag = true;
// 停止遍历数组a[n]
break;
}
}
// 相邻两项元素(b[j],b[j+1])之和不等于任何一个斐波那契数,则停止遍历b[n]
if (!flag)
break;
}
// 所有相邻两项元素之和等于某一个斐波那契数,则打印输出
if (flag)
{
for (long k = 0; k < n; k++)
cout << b[k] << "\t";
cout <<"K"<< endl;
}
// 遍历下一组排列b[n]
} while (next_permutation(b, b + n));
这段代码你自己优化下,比如冗余遍历、重复计算、变量冗余赋值等