C++入门教程,函数在C++中的作用(二)
作者:bea
oldLayout[1][ curSln ] > oldLayout[0][ curSln ] && oldLayout[0][ curSln ]以及是否
oldLayout[3][ curSln ] > oldLayout[2][ curSln ] && oldLayout[2][ curSln ]
并且保证各自不为负数以及没有和原来的方案冲突。检查是否和原有方案相同就是枚举所有原由方案以和当前方案比较,由于比较复杂,在此将其定义为函数,通过返回bool类型来表示是否冲突。
退回上一次方案或到下一个方案的选择,只用curSln--或curSln++即可。而是否所有人都过河,则只用oldLayout[0~1][ curSln ]都为0而oldLayout[2~3][ curSln ]都为3。而判断人数布局是否相同,则只用相应各元素是否相等即可。
第三步:下面剩下的就没什么东西了,只需要按照算法说的顺序,将刚才的各操作拼凑起来,并注意“重复直到所有人都过河了”转成do while即可。如下:
#include
// 分别表示一个商人、一个仆人、两个商人、两个仆人、一个商人一个仆人
char sln[5] = { ( 1 << 4 ), 1, ( 2 << 4 ), 2, ( 1 << 4 ) | 1 };
unsigned char curSln = 1;
char oldLayout[4][200], cur[200];
void DoSolution( char b )
{
unsigned long oldSln = curSln - 1; // 临时变量,出于效率
oldLayout[0][ curSln ] =
oldLayout[0][ oldSln ] - b * ( ( sln[ cur[ curSln ] ] & 0xF0 ) >> 4 );
oldLayout[1][ curSln ] =
oldLayout[1][ oldSln ] - b * ( sln[ cur[ curSln ] ] & 0xF );
oldLayout[2][ curSln ] =
oldLayout[2][ oldSln ] + b * ( ( sln[ cur[ curSln ] ] & 0xF0 ) >> 4 );
oldLayout[3][ curSln ] =
oldLayout[3][ oldSln ] + b * ( sln[ cur[ curSln ] ] & 0xF );
}
bool BeRepeated( char b )
{
for( unsigned long i = 0; i < curSln; i++ )
if( oldLayout[0][ curSln ] == oldLayout[0][ i ] &&
oldLayout[1][ curSln ] == oldLayout[1][ i ] &&
oldLayout[2][ curSln ] == oldLayout[2][ i ] &&
oldLayout[3][ curSln ] == oldLayout[3][ i ] &&
( ( i & 1 ) ? 1 : -1 ) == b ) // 保证过河后的方案之间比较,回来后的方案之间比较
// i&1等效于i%2,i&7等效于i%8,i&63等效于id
return true;
return false;
}
void main()
{
char b = 1;
oldLayout[0][0] = oldLayout[1][0] = 3;
cur[0] = oldLayout[2][0] = oldLayout[3][0] = 0;
for( unsigned char i = 0; i < 200; i++ ) // 初始化每次选择方案时的初始化方案为sln[0]
cur[ i ] = 0; // 由于cur是全局变量,在VC中,其已经被赋值为0
// 原因涉及到数据节,在此不表
do
{
DoSolution( b );
if( ( oldLayout[1][ curSln ] > oldLayout[0][ curSln ] && oldLayout[0][ curSln ] ) ||
( oldLayout[3][ curSln ] > oldLayout[2][ curSln ] && oldLayout[2][ curSln ] ) ||
oldLayout[0][ curSln ] < 0 || oldLayout[1][ curSln ] < 0 ||
oldLayout[2][ curSln ] 4 )
{
b = -b;
cur[ curSln ] = 0;
curSln--;
if( !curSln )
break; // 此题无解
goto P; // 重新检查以保证cur[ curSln ]的有效性
}
continue;
}
b = -b;
curSln++;
}
while( !( oldLayout[0][ curSln - 1 ] == 0 && oldLayout[1][ curSln - 1 ] == 0 &&
oldLayout[2][ curSln - 1 ] == 3 && oldLayout[3][ curSln - 1 ] == 3 ) );
for( i = 0; i < curSln; i++ )
printf( "%d %d %d %d ",
oldLayout[0][ i ],
oldLayout[1][ i ],
oldLayout[2][ i ],
oldLayout[3][ i ] );
}
上面数组sln[5]的初始化方式下篇介绍。上面的预编译指令#include将在《C++从零开始(十)》中说明,这里可以不用管它。上面使用的函数printf的用法,请参考其它资料,这里它只是将变量的值输出在屏幕上而已。
前面说此法是枚举法,其基本上属于万能方法,依靠CPU的计算能力来实现,一般情况下程序员第一时间就会想到这样的算法。它的缺点就是效率极其低下,大量的CPU资源都浪费在无谓的计算上,因此也是产生瓶颈的大多数原因。由于它的万能,编程时很容易将思维陷在其中,如求和1到100,一般就写成如下:
for( unsigned long i = 1, s = 0; i <= 100; i++ ) s += i;
但更应该注意到还可unsigned long s = ( 1 + 100 ) * 100 / 2;,不要被枚举的万能占据了头脑。
上面的人数布局映射成一结构是最好的,映射成char[4]所表现的语义不够强,代码可读性较差。下篇说明结构,并展示类型的意义——如何解释内存的值。
有用 | 无用猜你喜欢
您可能感兴趣的文章:
- 什么是C++中的虚拟克隆
- C++是什么《我的第一本C++书》
- C++中char*,String,int,CString间转换
- 解决C++客户端到C#服务器中文乱码
- 用C++如何实现八皇后问题
- C++如何动态创建二维数组
- 总结C++中指针的用法
- 如何用C++读取注册表信息
- 对C++初学者的一些忠告
- 说说C#和C++怎样混合编程
- C++教程之类的知识最后篇
- C++教程之类的相关知识(七)
- C++教程之类的相关知识(六)
- C++教程之类的相关知识(五)
- C++教程之类的相关知识(四)
- C++教程之类的相关知识(三)
- C++教程之类的相关知识(二)
- C++教程之类的相关知识(一)
- 介绍几本C++网络编程的书籍