NOI 2005 智慧珠游戏 zhzyx

使劲搜索,判了一下连通块(大小<3则剪枝,3 <= 大小 <= 5 则填入对应的棋子,无法填入则剪枝),另外搜索之前判一下棋盘上半、下半部分空格的数量关系,若上面的空格较多,则把棋盘对称变换一下。

 

/* * $File: zhzyx.cpp * $Date: Thu May 13 16:03:53 2010 +0800 */ #define INPUT "zhzyx.in" #define OUTPUT "zhzyx.out" #include <cstdio> #include <cstring> #include <cassert> namespace Solve { const int NSHAPE_ORIG = 12, SHAPE_SIZE_MIN = 3, SHAPE_SIZE_MAX = 5, BOARD_NRC = 10, NSHAPE_MAX = NSHAPE_ORIG * 8, BOARD_AREA = BOARD_NRC * (BOARD_NRC + 1) / 2; const char *SHAPE_ORIG_DESC[] = {"xxnx.", "xxxx", "xxxnx..", "xxnxx", "x..nx..nxxx", "xxxxn.x..", "xxxnx.x", "xxxnxx.", "xxx.n..xx", ".x.nxxxn.x.", "x..nxx.n.xx", "xxxxnx..."}; struct Matrix { int size, data[SHAPE_SIZE_MAX][SHAPE_SIZE_MAX]; void rotate(); void flip(); Matrix() : size(0) {memset(data, 0, sizeof(data));} }; struct Shape { int size, dr[SHAPE_SIZE_MAX], dc[SHAPE_SIZE_MAX], num; // dr, dc is related to the first bead of the first row void set_val(int num0, const Matrix &m); bool operator == (const Shape &n) const; bool check_fit(int row, int col); void put(int row, int col); void unput(int row, int col); }; Shape shape[NSHAPE_MAX]; int lshape_prev[NSHAPE_MAX + 5], lshape_next[NSHAPE_MAX + 5], lshape_head, lpos_prev[BOARD_AREA + 5], lpos_next[BOARD_AREA + 5], lpos_head, lpos_row[BOARD_AREA + 5], lpos_col[BOARD_AREA + 5], lpos_num[BOARD_NRC][BOARD_NRC]; int nshape, shape_block_start[NSHAPE_ORIG], shape_block_end[NSHAPE_ORIG]; void init(); struct Found{}; int board[BOARD_NRC][BOARD_NRC]; struct Shape_put { int snum, row, col; }; bool check(int row, int col, Shape_put *sp, int &nsp); void dfs(); void transform_board(); void solve(FILE *fin, FILE *fout); } void Solve::solve(FILE *fin, FILE *fout) { init(); shape[nshape].num = -1; int cnt_up = 0, cnt_down = 0; for (int i = 0; i < BOARD_NRC; i ++) { char str[BOARD_NRC + 5]; fscanf(fin, "%s", str); for (int j = 0; j <= i; j ++) if (str[j] != '.') { int s = shape_block_start[str[j] - 'A'], t = shape_block_end[str[j] - 'A']; board[i][j] = str[j] - 'A' + 1; lshape_next[lshape_prev[s]] = lshape_next[t]; lshape_prev[lshape_next[t]] = lshape_prev[s]; if (i + j < BOARD_NRC) cnt_up ++; else cnt_down ++; } } if (cnt_down > cnt_up) transform_board(); for (int i = 0; i < BOARD_NRC; i ++) for (int j = 0; j <= i; j ++) if (board[i][j]) { int n = lpos_num[i][j]; lpos_next[lpos_prev[n]] = lpos_next[n]; lpos_prev[lpos_next[n]] = lpos_prev[n]; } try { bool ok = true; Shape_put sput[NSHAPE_ORIG]; int nsput = 0; for (int i = 0; i < BOARD_NRC && ok; i ++) for (int j = 0; j <= i; j ++) if (!check(i, j, sput, nsput)) { ok = false; break; } if (ok) dfs(); } catch (Found) { if (cnt_down > cnt_up) transform_board(); for (int i = 0; i < BOARD_NRC; i ++) { for (int j = 0; j <= i; j ++) fputc(board[i][j] + 'A' - 1, fout); fputc('/n', fout); } return; } fprintf(fout, "No solution/n"); } void Solve::transform_board() { int b1[BOARD_NRC][BOARD_NRC]; memcpy(b1, board, sizeof(board)); memset(board, 0, sizeof(board)); for (int i = 0; i < BOARD_NRC; i ++) for (int j = 0; j <= i; j ++) board[i][j] = b1[BOARD_NRC - 1 - j][BOARD_NRC - 1 - i]; } void Solve::dfs() { if (lpos_next[lpos_head] == lpos_head) throw Found(); int row = lpos_row[lpos_next[lpos_head]], col = lpos_col[lpos_next[lpos_head]]; Shape_put sput[NSHAPE_ORIG]; int nsput = 0; for (int i = lshape_next[lshape_head]; i != lshape_head; i = lshape_next[i]) if (shape[i].check_fit(row, col)) { shape[i].put(row, col); bool ok = true; static const int DR[] = {-1, 1, 0, 0}, DC[] = {0, 0, -1, 1}; for (int j = 0; j < shape[i].size && ok; j ++) { int r = row + shape[i].dr[j], c = col + shape[i].dc[j]; for (int k = 0; k < 4; k ++) if (!check(r + DR[k], c + DC[k], sput, nsput)) { ok = false; break; } } if (ok) dfs(); for (int j = nsput - 1; j >= 0; j --) shape[sput[j].snum].unput(sput[j].row, sput[j].col); shape[i].unput(row, col); } } bool Solve::check(int row, int col, Shape_put *sput, int &nsput) { if (row < 0 || row >= BOARD_NRC || col < 0 || col > row || board[row][col]) return true; static bool visited[BOARD_NRC][BOARD_NRC]; memset(visited, 0, sizeof(visited)); struct Queue_node { int r, c; }; static Queue_node queue[BOARD_AREA]; int qh = 0, qt = 1, size = 1, row_min = row, col_min = col; queue[0].r = row; queue[0].c = col; visited[row][col] = true; static const int DR[] = {-1, 1, 0, 0}, DC[] = {0, 0, -1, 1}; while (qh < qt) { int rh = queue[qh].r, ch = queue[qh].c; qh ++; for (int register k = 0; k < 4; k ++) { int register r1 = rh + DR[k], c1 = ch + DC[k]; if (r1 >= 0 && r1 < BOARD_NRC && c1 >= 0 && c1 <= r1 && !visited[r1][c1] && !board[r1][c1]) { size ++; if (size > SHAPE_SIZE_MAX) return true; queue[qt].r = r1; queue[qt].c = c1; visited[r1][c1] = true; if (r1 < row_min || (r1 == row_min && c1 < col_min)) { row_min = r1; col_min = c1; } qt ++; } } } if (size < SHAPE_SIZE_MIN) return false; for (int i = lshape_next[lshape_head]; i != lshape_head; i = lshape_next[i]) if (shape[i].size == size && shape[i].check_fit(row_min, col_min)) { shape[i].put(row_min, col_min); sput[nsput].snum = i; sput[nsput].row = row_min; sput[nsput].col = col_min; nsput ++; return true; } return false; } bool Solve::Shape::check_fit(int row, int col) { for (int register i = 0; i < size; i ++) { int register r1 = row + dr[i], c1 = col + dc[i]; if (r1 < 0 || r1 >= BOARD_NRC || c1 < 0 || c1 > r1 || board[r1][c1]) return false; } return true; } void Solve::Shape::put(int row, int col) { int start = shape_block_start[num], end = shape_block_end[num]; lshape_next[lshape_prev[start]] = lshape_next[end]; lshape_prev[lshape_next[end]] = lshape_prev[start]; for (int i = 0; i < size; i ++) { int register r1 = row + dr[i], c1 = col + dc[i]; board[r1][c1] = num + 1; int n = lpos_num[r1][c1]; lpos_next[lpos_prev[n]] = lpos_next[n]; lpos_prev[lpos_next[n]] = lpos_prev[n]; } } void Solve::Shape::unput(int row, int col) { for (int i = size - 1; i >= 0; i --) { int register r1 = row + dr[i], c1 = col + dc[i]; int n = lpos_num[r1][c1]; lpos_prev[lpos_next[n]] = n; lpos_next[lpos_prev[n]] = n; board[r1][c1] = 0; } int start = shape_block_start[num], end = shape_block_end[num]; lshape_next[lshape_prev[start]] = start; lshape_prev[lshape_next[end]] = end; } void Solve::Shape::set_val(int num0, const Matrix &m) { num = num0; int r0 = 0, c0 = 0; while (m.data[r0][c0] == 0) { c0 ++; if (c0 == m.size) { r0 ++; c0 = 0; } } size = 0; for (int i = 0; i < m.size; i ++) for (int j = 0; j < m.size; j ++) if (m.data[i][j]) { dr[size] = i - r0; dc[size] = j - c0; size ++; assert(size <= SHAPE_SIZE_MAX); } } bool Solve::Shape::operator == (const Shape &n) const { if (size != n.size) return false; for (int i = 0; i < size; i ++) if (dr[i] != n.dr[i] || dc[i] != n.dc[i]) return false; return true; } void Solve::Matrix::rotate() { static int tmp[SHAPE_SIZE_MAX][SHAPE_SIZE_MAX]; memcpy(tmp, data, sizeof(data)); for (int i = 0; i < size; i ++) for (int j = 0; j < size; j ++) data[i][j] = tmp[size - 1 - j][i]; } void Solve::Matrix::flip() { for (int i = 0; i < size; i ++) for (int j = (size >> 1) - 1; j >= 0; j --) { int register x = data[i][j]; data[i][j] = data[i][size - 1 - j]; data[i][size - 1 - j] = x; } } void Solve::init() { for (int i = 0; i < NSHAPE_ORIG; i ++) { int r = 0, c = 0; Matrix cur_mat; for (const char *ptr = SHAPE_ORIG_DESC[i]; *ptr; ptr ++) { if (*ptr == 'n') { r ++; c = 0; } else { cur_mat.data[r][c] = (*ptr == 'x'); c ++; if (c > cur_mat.size) cur_mat.size = c; } } r ++; if (r > cur_mat.size) cur_mat.size = r; int ss = nshape; shape_block_start[i] = nshape; shape[nshape ++].set_val(i, cur_mat); for (int j = 0; j < 3; j ++) { cur_mat.rotate(); shape[nshape].set_val(i, cur_mat); int ok = 1; for (int k = ss; k < nshape; k ++) if (shape[nshape] == shape[k]) { ok = 0; break; } nshape += ok; } cur_mat.flip(); for (int j = 0; j < 4; j ++) { cur_mat.rotate(); shape[nshape].set_val(i, cur_mat); int ok = 1; for (int k = ss; k < nshape; k ++) if (shape[nshape] == shape[k]) { ok = 0; break; } nshape += ok; } shape_block_end[i] = nshape - 1; } for (int i = 0; i < nshape; i ++) { lshape_prev[i] = i - 1; lshape_next[i] = i + 1; } lshape_head = nshape; lshape_prev[0] = lshape_head; lshape_next[lshape_head] = 0; for (int i = 0, r = 0, c = 0; ; ) { lpos_prev[i] = i - 1; lpos_next[i] = i + 1; lpos_row[i] = r; lpos_col[i] = c; lpos_num[r][c] = i; i ++; c ++; if (c > r) { r ++; c = 0; if (r == BOARD_NRC) { assert(i == BOARD_AREA); break; } } } lpos_head = BOARD_AREA; lpos_prev[0] = lpos_head; lpos_next[lpos_head] = 0; } int main() { FILE *fin = fopen(INPUT, "r"), *fout = fopen(OUTPUT, "w"); Solve::solve(fin, fout); fclose(fin); fclose(fout); }

 

  Problem: zhzyx
    Point    Execution Status     Score         Time [sec]    Memory [kb] 
    1        Normal               10.000        0.094         2344        
    2        Normal               10.000        0.010         2344        
    3        Normal               10.000        0.028         2340        
    4        Normal               10.000        0.247         2344        
    5        Normal               10.000        0.014         2344        
    6        Normal               10.000        0.007         2292        
    7        Normal               10.000        0.022         2344        
    8        Normal               10.000        0.017         2344        
    9        Normal               10.000        0.006         2344        
    10       Normal               10.000        0.039         2288

你可能感兴趣的:(游戏,c,struct,File,qt,Matrix)