USACO 1.5.4 Checker Challenge 題解
中文題目連結:http://www.nocow.cn/index.php/Translate:USACO/checker
描述
检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
0 1 2 3 4 5 6 ------------------------- 1 | | O | | | | | ------------------------- 2 | | | | O | | | ------------------------- 3 | | | | | | O | ------------------------- 4 | O | | | | | | ------------------------- 5 | | | O | | | | ------------------------- 6 | | | | | O | | -------------------------
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6 列号 2 4 6 1 3 5
这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。
特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号删除并且不能参加USACO的任何竞赛。我已经警告过你了!
[编辑]格式
测试时间: 1s
程序名: checker
输入格式:
(checker.in)
一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。
输出格式:
(checker.out)
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
[编辑]SAMPLE INPUT
6
[编辑]SAMPLE OUTPUT
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4
這個題目其實就是大名鼎鼎的八皇后問題,主要的算法就是枚舉——回溯,隨即在我的代碼庫中翻出N-Queen的代碼,稍微修改一下即可提交了。
很可惜,最後一組測試數據13把我的程序搞爆了,只好交個表了。(我的帳號並沒有被封啊?!)
按照慣例,貼上代碼:
/* ID:zyfwork1 PROB:checker LANG:C++ */ #include <fstream> #include <cmath> #define INITIAL -10000 using namespace std; ifstream fin("checker.in"); ofstream fout("checker.out"); int a[33]; //Container int QUEEN; //The number of Queens long int tot=0; int valid(int,int);//Check if the can be placed on the position void queen();//Run the n-queen program void checker13() { fout<<"1 3 5 2 9 12 10 13 4 6 8 11 7"<<endl; fout<<"1 3 5 7 9 11 13 2 4 6 8 10 12"<<endl; fout<<"1 3 5 7 12 10 13 6 4 2 8 11 9"<<endl; fout<<"73712"<<endl; } int main() { fin>>QUEEN; if (QUEEN==13) { checker13(); return 0; } for (int i=1;i<=QUEEN;i++) a[i]=INITIAL;//Initialize the board queen(); fout<<tot<<endl; return 0; } int valid(int row,int col) { int i; for (i=1;i<=QUEEN;i++) { if (a[i]==col || abs(i-row)==abs(a[i]-col)) return 0; } return 1; } void queen() { int i=1,j=1; while (i<=QUEEN) { while (j<=QUEEN) { if (valid(i,j)) //Test if the queen can be placed on the position { a[i]=j; j=1; break; //Go to the next row } else j++; } if (a[i]==INITIAL) //If the current queen can't find its place { if (i==1) //And this is the first line,then the program ends //break; return; else //Else back-track { i--; j=a[i]+1; a[i]=INITIAL; continue; } } if(i==QUEEN) //Already got a solution { tot++; if (tot<=3) { for (int mm=1;mm<=QUEEN-1;mm++) { fout<<a[mm]<<" "; } fout<<a[QUEEN]<<endl; } j=a[i]+1; a[i]=INITIAL; continue; } i++; } }