编程之美读书笔记1.2——中国象棋将帅问题

http://blog.csdn.net/pipisorry/article/details/36380669

问题:下过中国象棋的朋友都知道,双方的“将”和“帅”相隔遥远,并且它们不能照面。在象棋残局中,许多高手能利用这一规则走出精妙的杀招。假设棋盘上只有“将”和“帅”二子(如图1-3所示)(为了下面叙述方便,我们约定用A表示“将”,B表示“帅”):

AB二子被限制在己方3×3的格子里运动。例如,在如上的表格里,A被正方形{d10f10d8f8}包围,而B被正方形{d3f3d1f1}包围。每一步,AB分别可以横向或纵向移动一格,但不能沿对角线移动。另外,A不能面对B,也就是说,AB不能处于同一纵向直线上(比如Ad10的位置,那么B就不能在d1d2以及d3)。

请写出一个程序,输出AB所有合法位置。要求在代码中只能使用一个变量

分析:

题目中仅仅是要求判断将与帅是否照面,而将与帅只能在各自的9个位置移动,因而只需要形式化1~9这9个数字。

此题的解法一中的常规解决手段,即是位操作。一般是定义一系列的掩码(masks)——可以用宏定义,或者枚举类型——来完成。

参考代码:

/****************************************************************************/
/*	1.2中国象棋将帅问题		皮皮 2014-7-1	       		    */
/****************************************************************************/
#include <stdio.h>

typedef struct bitField{
	unsigned char a:4;
	unsigned char b:4;
}bit;

void chessTest1(){
	char column = 1;
	for(; column <=3 ; column ++){			//A的列选
		for(; column <= 9; column += 3){	//A(和B)的行选
			printf("A = %d, B = %d\n", column, column%3 + 1);
			printf("A = %d, B = %d\n", column, column%3 + 1 + 3);
			printf("A = %d, B = %d\n", column, column%3 + 1 + 6);
			printf("A = %d, B = %d\n", column, (column + 1)%3 + 1);
			printf("A = %d, B = %d\n", column, (column + 1)%3 + 1 + 3);
			printf("A = %d, B = %d\n", column, (column + 1)%3 + 1 + 6);
		}
		column -= 9;
	}
}

void chessTest2(){
	char i = 81;
	while(i--){
		if(i/9 % 3 == i % 9 %3)	//i/9(A的编号-1[0~8]) % 3(A的列); i%9(B的编号-1[8~0]) %3
			continue;			//同列则continue
		printf("A = %d, B = %d\n",i/9 + 1, i%9 + 1);
	}
}

void chessTest3(){
	bit 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)	//A B不同列
				printf("A = %d, B = %d\n", i.a, i.b);
}

void main(){<span style="font-family: Arial, Helvetica, sans-serif;">     chessTest3();</span><span style="font-family: Arial, Helvetica, sans-serif;">}</span>

说明:

1.看chessTest1,其实只需要printf就可以输出正解,只要AB不同列就可以,共3*3 * 2*3 = 54种情况

2.chessTest2比较不好想,只要注意AB编号不能同时相同(if判断语句中)且AB不同列时才输出就可以

<span style="font-size:12px;">3.chessTest3使用了位域方法,位域知识参见:http://blog.csdn.net/pipisorry/article/details/36220851</span>

位域的概念《C程序设计语言》用了一页纸介绍,说明了应用场合主要是为了节省空间或直接访问位,应用场景如编译器的符号表以及一些硬件的驱动程序。网络开发、信息编码压缩解压缩、位图等方面可能还会用到,其余的场景多半会去讨论怎么节省时间开销,让程序运行的更加高效。

此外还有一种位读写方式是STL库中提供的泛型类bitset,它支持对位赋值的操作,也支持整体的位运算,最方便的是输入输出流被重载,很容易查看对应的位是否被置正确。相比于位域,bitset不能支持局部几个比特位的访问,而这正是位域的优势。不过对将与帅的问题,要求一个字节,而bitset基本的对齐是4个字节,所以可能不符合题目要求,不过对于其它的位操作场合却是一种很好的选择。

位域的概念《C程序设计语言》用了一页纸介绍,说明了应用场合主要是为了节省空间或直接访问位,应用场景如编译器的符号表以及一些硬件的驱动程序。我想做网络开发、信息编码压缩解压缩、位图等方面可能还会用到,其余的场景多半会去讨论怎么节省时间开销,让程序运行的更加高效。

from:http://blog.csdn.net/pipisorry/article/details/36380669

编程之美读书笔记1.2——中国象棋将帅问题

时间: 2024-10-12 12:41:55

编程之美读书笔记1.2——中国象棋将帅问题的相关文章

《编程之美-读书笔记》-1 中国象棋将帅问题

时间:2014.05.27 地点:基地 ---------------------------------------------------------------------------------------- 一.指针和引用的区别 1.指针可以为空,引用不可以不空. 引用是一个对象的别用,定义一个引用时必须初始化,而声名指针时可以不指向任何对象,故使用指针时也常要做空的判断,而引用无需,因为引用总是绑定着一个对象. 2.指针可以改变指向,而引用不可以重新绑定新对象.(指针变异思迁,引用从

编程之美读书笔记1.8 - 小飞的电梯调度算法

http://blog.csdn.net/pipisorry/article/details/36688019 问题: 亚洲微软研究院所在的希格玛大厦一共有6部电梯.在高峰时间,每层都有人上下,电梯每层都停.实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法: 由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层.所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层.在一楼的时候,每个乘客选择自己的目

编程之美读书笔记2.15 - 子数组之和的最大值(二维)

http://blog.csdn.net/pipisorry/article/details/39083073 问题: 求二维数组(矩阵)的子矩阵之和的最大值. 亦可见:http://poj.org/problem?id=1050 解法1:(解释见注释) 每个子矩阵由列长.行长和左上角的元素位置决定.如果我们指定左上角的元素位置 (i,j) 和列长 c,那么可以求所有这些子矩阵中和最大的.然后,变化列长 c,可以求以 (i,j) 为左上角的最大和子矩阵.最所有左上角位置再求最大和子矩阵,问题就解

编程之美读书笔记1.1——让CPU占用率曲线听你的指挥

http://blog.csdn.net/pipisorry/article/details/36189155 <strong><span style="font-size:48px;color:#ff0000;">问题:</span></strong>写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率. 假设机器是多CPU,上面的程序会出现什么结果?怎样在多个CPU时显示相同的状态?比如.在双核的

编程之美读书笔记2.14 - 子数组之和的最大值

http://blog.csdn.net/pipisorry/article/details/39083281 问题: 1. 一个由N个整数元素的一维数组,求其所有子数组中元素和的最大值. 2. 如果数组首尾相邻,也就是允许子数组A[i],...,A[n-1],A[0],...,A[j]存在,求其所有子数组总元素和的最大值. 解法1: /* O(n^2) 遍历算法 */ static int maxSubarraySum1(int *a,int a_len){ int max_sum = INT

编程之美读书笔记之---”不要被阶乘吓到“

问题一:给定一个整数N,那么N的阶乘末尾有多少个0呢?例如N = 10, N! = 362800,N! 的末尾有两个0. 问题二:求N! 的二进制表示中,最低位1的位置. 问题一的解法一: 最简单的方法就是把N! 算出来,就可以知道末尾有多少个0了. 问题一的解法二: 我们这样想,末尾的0可以从哪里得到呢,10的倍数,例如像10,20,100....这样的,可以贡献0,还有就是2 * 5这样也可以得到一个0,不过我们可以发现,10其实也是从5得来的, 10 = 2 * 5, 20 = 4 * 5

《编程之美》读书笔记:中国象棋将帅问题

找出将和帅所有可能的局面,要求用一个字节的变量来存储数据. 我最初分析这道题,想可以枚举将的位置,那么一共有9个,再写出帅的位置就行,由于将帅不能照面,所以此时帅只有6个位置.答案必定有9*6=54个.只是判断照面的地方会比较麻烦. 由于只有一个字节的变量限制和以前做题经验,使我一度想歪以为要用二进制的位来表示将的位置.但是这样的话,一个字节只有8位,而将可有9个位置,显然不行. 当然,不应这样做,也没有必要这样. 后来想到另一种思路,可以把将和帅的位置同时压缩到一个十进制数字N里面,这样N=a

编程之美笔记--第一章游戏之乐--1.2中国象棋将帅问题

后来一版作者又将最后一句改为:”要求在代码中只能使用一个字节存储变量“. 我的解法: package android.zlb.java; /** * * @author zhanglibin * */ public class TestXiangqi { public static void main(String[] args) { for(int i = 11; i < 100; i++) { if(i / 10 % 3 == 1 && (i % 10 == 1 || i % 1

VC++编程之道读书笔记(2)

第三篇 技术细节 第七章:细说开发人员必知必会的39个开发细节 细节36:单例模式的应用 在开发程序时,往往需要在整个工程中只需要一个类的实例.而这个实例一旦被创建就不能被其他的实例再创建了,通常我们称这个实现过程为单例模式. 既然要保证类只有一个实例,那么就需要其他的类不能使用实例化该类.因此,需要将其构造方法设为私有的,即使用private关键字修饰.同时,类中提供一个静态方法,该方法的返回值是该类的一个实例.这样就只能使用该静态方法来获取类的实例了,从而保证了唯一性. 下面通过具体代码来实