USACO 1.5 Checker Challenge (DFS + 剪枝)

来源:互联网 发布:手机蝴蝶恶作剧软件 编辑:程序博客网 时间:2024/05/17 09:06
#include <stdio.h>#define DEBUG 1#define TESTCASES 8#define IN(x)  ( (x) >= 1 && (x) <= size ? 1 : 0 )#define WITHIN(x, y) ( IN(x) && IN(y) ? 1 : 0 )int size;int sizeIsEven;int halfSize;int conflict[14][14];int solution[14];int numOfSolutions;//剪枝:对角线冲突只要标记左下和右下两个方向int directionArray[2][2] = {{1, 1}, {1, -1}};void printConflict(){int i, j;for (i = 1; i <= size; i++)for (j = 1; j <= size; j++)printf("%d%c", conflict[i][j], j == size ? '\n' : ' ');printf("\n");}void setConflict(int row, int column, int flag){int i; for (i = 1; i <= size; i++)conflict[i][column] += flag;int directionIndex;for (directionIndex = 0; directionIndex < 2; directionIndex++){int deltaX = directionArray[directionIndex][0];int deltaY = directionArray[directionIndex][1];int x = row + deltaX;int y = column + deltaY;while ( WITHIN(x, y) ){conflict[x][y] += flag;x += deltaX;    y += deltaY;}}}void placeQueen(int row, int sum){//printConflict();if (row == size){//剪枝:最后一行放棋子的列号可以算出来int temp = (1 + size) * size / 2 - sum;if (conflict[size][temp] == 0){solution[size] = temp;if (++numOfSolutions < 4){int i;for (i = 1; i <= size; i++)printf("%d ", solution[i]);printf("\n");}}return;}int column;for (column = 1; column <= size; column++){//剪枝:size为偶数时对称优化,size为奇数时怎么优化呢?if ( row == 1 && sizeIsEven && column  ==  halfSize + 1 && numOfSolutions >= 3){numOfSolutions *= 2;return;}if (conflict[row][column] == 0){solution[row] = column;setConflict(row, column, 1);placeQueen(row + 1, sum + column);setConflict(row, column, -1);}}}int main(){#if DEBUGint testCase;for (testCase = 1; testCase <= TESTCASES; testCase++){char inputFileName[20] = "inputx.txt";inputFileName[5] = '1' +  (testCase - 1);freopen(inputFileName, "r", stdin);printf("\n#%d\n", testCase);#endifscanf("%d", &size);halfSize = size >> 1;sizeIsEven = !(size & 1);numOfSolutions = 0;placeQueen(1, 0);printf("%d\n", numOfSolutions);#if DEBUG}#endifreturn 0;}


                                             
0 0