/* 移除列 c 以及与列 c 连接的所有行上的元素 remove 操作并不在实际上移除任何元素,而是令两侧的指针跨越被移除元素,通过更新列大小 siz 被移除的行和列依然能够被对应的行指针和列节点 */ voidremove(constint &c){ int i, j; L[R[c]] = L[c], R[L[c]] = R[c]; for (i = D[c]; i != c; i = D[i]) for (j = R[i]; j != i; j = R[j]) U[D[j]] = U[j], D[U[j]] = D[j], --siz[col[j]]; }
/* 恢复列 c 以及与列 c 连接的所有行上的元素 remove 操作的逆操作 */ voidrecover(constint &c){ int i, j; for (i = U[c]; i != c; i = U[i]) for (j = L[i]; j != i; j = L[j]) U[D[j]] = D[U[j]] = j, ++siz[col[j]]; L[R[c]] = R[L[c]] = c; }
booldance(int dep = 1, bool find_one_solution = true){ // 搜索第一个解 if (!R[0]) { crd = dep - 1; return find_one_solution; } int i, j, c = R[0]; for (i = R[0]; i != 0; i = R[i]) if (siz[i] < siz[c]) c = i; remove(c); for (i = D[c]; i != c; i = D[i]) { stk[dep] = row[i]; for (j = R[i]; j != i; j = R[j]) remove(col[j]); if (dance(dep + 1)) return1; for (j = L[i]; j != i; j = L[j]) recover(col[j]); } recover(c); return0; } } solver;
booldance(int dep = 1){ if (R[0] > extra) { // extra = 2 * n crd = dep - 1; return1; } int i, j, c = R[0]; for (i = R[0]; i != 0; i = R[i]) if (i <= extra && siz[i] < siz[c]) c = i; remove(c); for (i = D[c]; i != c; i = D[i]) { ret[dep] = row[i]; for (j = R[i]; j != i; j = R[j]) remove(col[j]); if (dance(dep + 1)) return1; for (j = L[i]; j != i; j = L[j]) recover(col[j]); } recover(c); return0; }
int num_block = 16; int count[6] = {3, 4, 2, 2, 2, 3}; int shape[6][3] = {{1, 1, 3}, {1, 2, 2}, {1, 2, 4}, {1, 4, 4}, {2, 2, 2}, {2, 2, 3}}; int dir_[6] = {3, 3, 6, 3, 1, 3}; int dir[16]; int block[16][3]; int idx[17]; int id_map[4000][6];
voidinsertBlock_dir(int x, int y, int z, int cur_idx, int num){ int a = 6 - x, b = 6 - y, c = 6 - z; for(int i = 0; i < a; ++i) { for(int j = 0; j < b; ++j){ for(int k = 0; k < c; ++k) { int id = cur_idx + i * b * c + j * c + k; for(int dx = i; dx < i + x; ++dx) for(int dy = j; dy < j + y; ++dy) for(int dz = k; dz < k + z; ++dz) solver.insert(id + 1, dx * 25 + dy * 5 + dz + 1); id_map[id + 1][0] = i; id_map[id + 1][2] = j; id_map[id + 1][4] = k; id_map[id + 1][1] = i + x; id_map[id + 1][3] = j + y; id_map[id + 1][5] = k + z; solver.insert(id + 1, 125 + num + 1); } } } }
voidinsertBlock(int num){ int cur_idx = idx[num], x, y, z; for(int i = 0; i < dir[num]; ++i) { switch (i) { case0: x = block[num][0]; y = block[num][1]; z = block[num][2]; break; case1: x = block[num][1]; y = block[num][2]; z = block[num][0]; break; case2: x = block[num][2]; y = block[num][0]; z = block[num][1]; break; case3: x = block[num][0]; y = block[num][2]; z = block[num][1]; break; case4: x = block[num][1]; y = block[num][0]; z = block[num][2]; break; case5: x = block[num][2]; y = block[num][1]; z = block[num][0]; break; } insertBlock_dir(x, y, z, cur_idx, num); cur_idx += (6 - block[num][0]) * (6 - block[num][1]) * (6 - block[num][2]); } }
intmain(){ for(int i = 0, p = 0; i < 6; ++i) { for(int j = 0; j < count[i]; ++j) { block[p][0] = shape[i][0]; block[p][1] = shape[i][1]; block[p][2] = shape[i][2]; dir[p] = dir_[i]; ++p; } } idx[0] = 0; for(int i = 0; i < num_block; ++i) idx[i + 1] = idx[i] + dir[i] * (6 - block[i][0]) * (6 - block[i][1]) * (6 - block[i][2]); solver.build(idx[num_block], 125 + num_block); for(int i = 0; i < num_block; ++i) insertBlock(i); solver.dance(); for (int i = 1; i <= solver.crd; ++i) { int id = solver.ret[i]; for(int j = 0; j < 6; ++j) printf("%d", id_map[id][j]); } return0; }
运行这段代码可以直接得到 flag1 ,程序运行耗时 1.540 s ,使用 O2 编译命令之后来到了 0.768s。