Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1 8 5 0
Sample Output
1 9210
只能说代码改了好久,脑子总是转不过来,用空间换取时间
第一种方法,只标记列,通过行与行的差和列与列的差计算是否在45度角上
#include <iostream> #include <cstdio> #include <cstring> int n, num; int ma[15]; int vis[15]; int ans[15]; using namespace std; //逐行添加 //第一行占了某一列,则将这一列全部标记 //和45度方向都标记 //阿西吧,想了好久才发现,四十五度上一行标记过, //再下一行标记,然后取消标记会把第一行的标记也给取消,一万点生气 //最后还超时,啊啊啊啊啊啊 //只标记列,通过行与行的差和列与列的差进行判断45度 //啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊还是超时一万点崩溃,事先保存? void dfs(int h) { if(h == n + 1) { num++; return; } for(int i = 1; i <= n; i++) { //这一行没有被遍历过 //也就是说这一列之前是没有放过皇后的 if(!vis[i]) { //保存的是列 ma[h] = i; //还要判断是否在45度角上 //也就是行与行的差,列与列的差不相等 int j; for(j = 1; j < h; j++) { //45度 if((ma[h] - ma[j] == (h - j)) || (ma[h] - ma[j] == (j - h))) break; } if(j == h) { vis[i] = 1; dfs(h + 1); vis[i] = 0; } } } return; } int main() { for(int i = 1; i <= 10; i++) { num = 0; n = i; memset(ma, 0, sizeof(ma)); memset(vis, 0, sizeof(vis)); dfs(1); ans[i] = num; } while(~scanf("%d", &n)) { if(n == 0) break; printf("%d\n", ans[n]); } return 0; }
第二种,也就是我最开始写的,列和45度方向都标记,总是超时,后来换用只标记列的方法依旧超时,超时在可以用空间来换取时间,一开始就将答案保存到数组当中,就不会超时了,所以我最开始的方法不再超时
#include <iostream> #include <cstdio> #include <cstring> int n, num; int ma[15][15]; int ans[15]; using namespace std; //逐行添加 //第一行占了某一列,则将这一列全部标记 //和45度方向都标记 //阿西吧,想了好久才发现,四十五度上一行标记过, //再下一行标记,然后取消标记会把第一行的标记也给取消,一万点生气 //标记为行值 void biaoji(int h, int l) { for(int i = h + 1; i < n; i++) { if(ma[i][l] == -1) { ma[i][l] = h; } } for(int i = 1; h + i < n; i++) { if(l + i < n) { if(ma[h + i][l + i] == -1) { ma[h + i][l + i] = h; } if(l - i >= 0) { if(ma[h + i][l - i] == -1) { ma[h + i][l - i] = h; } } } else if(l - i >= 0) { if(ma[h + i][l - i] == -1) { ma[h + i][l - i] = h; } } } return; } void quxiaobiaoji(int h, int l) { for(int i = h + 1; i < n; i++) { if(ma[i][l] == h) { ma[i][l] = -1; } } for(int i = 1; h + i < n; i++) { if(l + i < n) { if(ma[h + i][l + i] == h) { ma[h + i][l + i] = -1; } if(l - i >= 0) { if(ma[h + i][l - i] == h) { ma[h + i][l - i] = -1; } } } else if(l - i >= 0) { if(ma[h + i][l - i] == h) { ma[h + i][l - i] = -1; } } } return; } void dfs(int h, int sum) { for(int i = 0; i < n; i++) { //某行逐个标记? if(ma[h][i] == -1) { //还要放足n个 if(h == n - 1 && sum == n - 1) { num++; } else { ma[h][i] = h; biaoji(h, i); dfs(h + 1, sum + 1); //printf("%d\n", num); quxiaobiaoji(h, i); ma[h][i] = -1; } } } return; } int main() { for(int i = 1; i <= 10; i++) { n = i; memset(ma, -1, sizeof(ma)); num = 0; dfs(0, 0); ans[i] = num; } while(~scanf("%d", &n)) { if(n == 0) break; printf("%d\n", ans[n]); } return 0; }