编程之美将帅不照面

编程之美上的一道题:要求将帅不能照面,找到有多少种方式摆放“将”和“帅”,而且只能使用一个变量。

思考:如果蛮力法解决,只需要罗列出所有的可能性,然后排除掉那些不满足条件的情况就是结果了。但是,这里只能用一个变量保存结果,所以,需要一点技巧,先说一下《编程之美》是的解法2,因为解法2是最精妙的,个人认为,提供了一种新型的思考方式。先给出将帅在棋局的分布,有一个感观的认识再继续下面的操作:

《编程之美将帅不照面》

解法二:我们可以这么做,下面的二维特殊数k{1,2,3,4,5,….9},其中k=1,2,3,4,…..9.表示A中的k和B中的1,2,…9搭配成一对,这样子的话就可以搭配出9*9=81种可能性.理论上,我们只需要遍历完这81种情况就可以找到结果。A格子和B格子的棋子只有在同一列才会产生冲突。那么重点就是如何找到列数。

先列举出所以的可能性组合:

1{1,1}{1,2}{1,3}{1,4}{1,5}{1,6}{1,7}{1,8}{1,9}
2{2,1}{2,2}{2,3}{2,4}{2,5}{2,6}{2,7}{2,8}{2,9}
3{3,1}{3,2}{3,3}{3,4}{3,5}{3,6}{3,7}{3,8}{3,9}
4{4,1}{4,2}{4,3}{4,4}{4,5}{4,6}{4,7}{4,8}{4,9}
5{5,1}{5,2}{5,3}{5,4}{5,5}{5,6}{5,7}{5,8}{5,9}
6{6,1}{6,2}{6,3}{6,4}{6,5}{6,6}{6,7}{6,8}{6,9}
7{7,1}{7,2}{7,3}{7,4}{7,5}{7,6}{7,7}{7,8}{7,9}
8{8,1}{8,2}{8,3}{8,4}{8,5}{8,6}{8,7}{8,8}{8,9}
9{9,1}{9,2}{9,3}{9,4}{9,5}{9,6}{9,7}{9,8}{9,9}

第1行就是A中第1格和B中的九格对应的情况,其它类比如是

像for(i=1;i<=81;++i)中的i,

如果我们想确定它是A中的第几格,怎么办?可以对i除以9,就知道它是第几行,即A中第几格,如果还想知道它在A中第几列,继续对它模3即可。

现在开始考虑B中的情况,如何知道当前i是B中的第几格?这个问题可以转化成如何知道它是上面二维数组中第几列,只需要对i模上9即可,那么如何知道它是B中的第几列呢?继续对它模上3即可。

小结拓展:

我们知道A[i][j]实质上表示的是A数组中(i*cols+j)号元素,那么,如果我们知道元素是第k号元素了,要如何确定它的行号和列号呢?row=k/cols,col=k%cols.再把这个基本思路套到上面应该能够找到一点灵感了。

#include<stdio.h>
int main()
{
	int i=81;
	while(i--)
	{
		if( i/9%3 == i%9%3)//i/9求的是行号(A中号码),i%9求的是列号(B中号码)
			continue;
		printf("%d %d\n",i/9+1,i%9+1);//输出A,B中的号码
	}
}

总结:

可以将A中的9个格子{1,2,3,4,5,6,7,8,9}当成行号,将B中的9个格子{1,2,3,4,5,6,7,8,9}当成列号,那么就可以组成一个A[i][j]二维数组,只不过题目要求我们只能使用一个变量,否则我们只需要保存两个变量i,j,遍历完整个数组就可以了。但是,我们也可以用一维数组的方式存储二维数组的下标,假定一维数组的下标是k,则i=k/cols,j=k%cols.

这让我想到这篇博文的35和36行。http://blog.csdn.net/linraise/article/details/12571025

剩下的就可以完全按照二维数组的形式解决这个问题了。

解法三:用一个结构体保存两个变量,实质上和直接使用二维下标的思路一样。这里不再多说。

int main()
{
	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)
		{
			if( i.a % 3 != i.b % 3)
				printf("A = %d, B = %d\n",i.a,i.b);
		}
	}
}

    原文作者:Raise
    原文地址: https://blog.csdn.net/linraise/article/details/12888303
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞