题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。 上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下: 行号 1 2 3 4 5 6 列号 2 4 6 1 3 5 这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。 //以下的话来自usaco官方,不代表洛谷观点 特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号删除并且不能参加USACO的任何竞赛。我警告过你了! 输入输出格式 输入格式: 一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。 输出格式: 前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。 输入输出样例 输入样例#1: 6 输出样例#1: 2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4 说明 题目翻译来自NOCOW。 USACO Training Section 1.5 eg.自己在保存前三条路径的时候没有想好,因为对于一个路径而言,可能是前面部分的路径是相同的,如果是使用三个数组保存三条径路,那么会因为只在相同的路径进行递归的时候进入一次,不能两次都进入,所有要使用一个数组记录路径比较安全。 #include<iostream> #include<algorithm> #include<string> #include<cstring> using namespace std; int vis1[50],vis2[50],vis3[50]; int road[14],n; void dfs(int dep,int &res) { if(dep==n+1) { res++; if(res<=3) { for(int i=1;i<=n;i++) if(i!=n) cout << road[i]<<" "; else cout << road[i] << endl; } } for(int i=1;i<=n;i++) { if(!vis1[dep+i] && !vis2[n+dep-i] && !vis3[i]) { vis1[dep+i]=vis2[n+dep-i]=vis3[i]=1; road[dep]=i; dfs(dep+1,res); vis1[dep+i]=vis2[n+dep-i]=vis3[i]=0; } } } int main(void) { cin >> n; int res=0; dfs(1,res); cout << res; return 0; }