logo资料库

川大ACM1082不甘心的皇后.docx

第1页 / 共3页
第2页 / 共3页
第3页 / 共3页
资料共3页,全文预览结束
不甘心的皇后
不甘心的皇后 http://acm.scu.edu.cn/soj/problem.action?id=1082 这是我做过印象最深刻的编程作品--皇后问题,我把对它的理解和分析过程整理 在这里了,希望老师过目。我自己也经常关注 ACM,并且希望在之后的学习生活 中能够参加到 ACM 比赛中去锻炼思维,从中获得快乐。 印象最深刻的程序 #include #include #include int how,zero[10]; int main() { # 变量 how 表示放置的皇后种数,zero 数组存放皇后的位置 void count(int* q, int length, int now); while (1) { int n, queen[10]; scanf_s("%d", &n); if (n == 0) { break; # n 表示棋盘大小,queen 是存放皇后的数组,最多十个皇后。 # 输入 n # 如果棋盘边长为 0,则无法放置皇后 # 跳出循环 } memset(zero, -1, sizeof(zero)); # 将 zero 数组中的值都初始化为-1 how = 0; for (int i = 0; i < n; i++) { scanf_s("%d",&queen[i]); if (queen[i] == 0) { # 输入每列已有的皇后位置 # 如果皇后位置为 0,表示这一列还没有皇后 zero[i] = 0; # 那么 zero 数组中对应的列值也为 0 # 从第一列开始计算可放置皇后的方法数 # 输出该棋盘可放置皇后的方法种数 } } count(queen, n, 0); printf("%d\n", how); } return 0; } # 比较两个数大小,输出较大的一个值 int max(int a, int b) { if (a > b) { return a; } else { } return b;
} # 计算满足要求的情况数量 void count(int *q,int length,int now) { # 函数变量:queen 数组,棋盘大小,当前列值 if (now == length) { # 如果当前位置等于棋盘大小 int var; for (var = 0; var < length-1&&pow(q[var]-q[var+1],2)<=1; var++) { # 从第一列开始遍 # 设置整数变量 历,如果每两个相邻列皇后之间的行距离大于 1,则停止遍历 ; } if (var == length - 1)how++; # 如果停止遍历后的 var 正好等于 length-1,即已经遍 历完所有列,则说明这种放置皇后的方法是正确的,方法数加 1 return; } if (zero[now]==0) { if (now==0) { # 如果当前列没有皇后 # 如果是第一列 for (int j = 1; j <= length; j++) { # 从第一列的每一行开始遍历 q[now] = j; count(q, length, now + 1); # 计算第一列皇后在第 j 行时,棋盘可放 置皇后种数 } } else { # 如果不是第一列,那么该列皇后的位置范围应为[前一 列皇后位置-1,前一列皇后位置+1] for (int j = max(1,q[now-1]-1); j <= length&&j<=q[now-1]+1; j++) { # max(1,q[now-1]-1) 是为了确保皇后位置最小是 1 q[now] = j; count(q, length, now + 1); # 计算当前列皇后在第 j 行时,棋盘可放置皇 后种数 } } } else { } count(q, length, now + 1); # 当前列皇后已确定,计算后续列棋盘可放置皇后种数 } 采用递归调用函数的思想,算法思路如下: 1、 从棋盘的第一列开始,判断当前列的皇后位置是否已经确定。若每一列皇后位置已经确 定,则跳到下一行。若尚未确定,则根据上一列皇后的位置确定该列皇后位置的范围, 然后在此范围内依次遍历,调用 count 函数计算棋盘可放置皇后种数。 注意:第一列比较特殊,需要单独处理。因为当第一列的皇后位置不确定时,它可以在 任意一行。所以单独计算。
而对于其它列,该列皇后的位置范围应为[前一列皇后位置-1,前一列皇后位置+1]。 另外,为了避免前一列皇后位置-1=0 的情况,这时该列皇后位置是无意义的,所以添 加了一个 max 函数,取“前一列皇后位置-1”的值和 1 的较大值。 2、 当遍历到最后一列时,所有皇后摆放完毕,判断当前摆放的棋盘是否满足题目要求。即 采用 for 循环判断每两个相邻列皇后之间的行距离是否都小于等于 1。如果满足题目要 求,则摆放皇后种数增加 1。函数终止。 理解和总结: 这道题和八皇后问题有些类似。但是条件不同,这道题需要确保棋盘中每两个相邻列的 皇后之间的行距离最多只能差一格。所以只有先确定第一列的皇后位置,才能确定第二列的 皇后位置,继而确定第三列、第四列等等。而每一列的皇后位置又有多种可能,因此想到使 用深度优先搜索算法。对于每一列的可选择皇后位置中,选择一个位置作为出发点,然后依 次从该点出发搜索下一列可能的皇后位置,直至棋盘中所有列都被搜索过为止,然后判断这 条路径是否满足题目要求。 虽然我的编程水平还达不到做此类题目游刃有余,但我很享受沉浸其中思考解决编程思 维问题的过程。
分享到:
收藏