编程之美-中国象棋将帅问题

来源:互联网 发布:策划程序美工音效 编辑:程序博客网 时间:2024/05/01 03:20

题目:中国象棋中将帅两子被限制在3*3的格子中,将帅不能碰面,并且只能纵向或横向移动。请写出一个程序输入将帅的合法位置。(要求代码中只能有一个变量)

这样,由于最后要输出将帅不能碰面的位置编号,所以先分别对将帅的3*3格子进行编号1-9。

我第一步是想用双重循环来做,但是那样就不是只使用一个变量了,也感觉没那么简单,就直接放弃直接看方法了,然后我承认第一种方法可以,但是很复杂,放弃了好几天,最后才觉得第一种方法可以忽略,因为编程提倡简约美!能用简单的代码写出来绝不用复杂代码写。
其实我总结了,做任何算法题有一种办法就是通用的,即暴力破解法,当然效率很差,例如这道题我们可以双循环全部判断,则效率低并且不符合要求。但是暴力破解法是有用的,例如这道题最后比较好的答案就是根据暴力破解法优化的,(我总结了算法解决方法有两种:1,先暴力破解,然后从中优化;2,找规律,直接写代码;3,使用算法导论中的方法如动态规划、平摊分析、贪心等来解决。这几种方法在后面的博客中都会涉及。)

接下来使用暴力破解法来解这道题:

for (int i = 1; i <= n; i++)

for (int j = 1; j <= n; j++)

{

if (i%3 == j%3)

{continue;}

else

{

printf("将=%d,帅=%d", i, j);

}

}

然后我们考虑题目要求,只使用一个变量,我想起了大学时老师讲的一种遍历数组的方法,根据除和取余,如:

int main()
{
int a[1][2][3] = {2, 3,4 ,5 ,6 ,7};
unsigned char x = 6;
while (x--)
{
printf("%3d", a[x/(2*3)][x/3][x%3]);
}
return 0;
}

同样,双重循环也可以改为单循环,即:

unsigned char x = 81;//9*9

while(x--)

{

if (x/9%3 == x%9%3)

continue;

else

printf(".....");

}

和编程之美的解法不谋而合,然而编程之美的第一种解法是定义一个byte数据然后分为前后两端字节分别存储将帅之后遍历判断,好繁琐,代码要简约。

至于第三种解法定义了一个结构体:

struct 

{

unsigned char a:4;

unsigned char b:4;

}i;

for (i.a = 1; i.a <= 9; i.a++)

for(i.b = 1; i.b <=9; i.b++)

{.....}//同上

好吧,题目要求只使用一个变量,是一个结构体变量。


触类旁通:当以后碰到有关循环优化、数组遍历优化、限制变量个数可以考虑这个方法。


原创粉丝点击