bool dlx(int k) { if(R[head]==head) { //È«²¿ÌîÍê ans(); return true; } int s=INF,c; //ÕÒ1×îÉÙµÄÁжÔÓ¦µÄµÚÒ»¸ö1µÄλÖÃi for(int i=R[head];i!=head;i=R[i]) if(S[i]<s) s=S[i],c=i; remove(c); //ɾ³ýc¶ÔÓ¦µÄÁÐ for(int i=D[c];i!=c;i=D[i]) { int x = to[row[i]][0] , y = to[row[i]][1], z = to[row[i]][2]; sudoku[x][y] = z; for(int j=R[i];j!=i;j=R[j]) remove(C[j]); //ɾ³ýÄÇÒ»ÐÐÓÐ1µÄÁÐ if(dlx(k+1)) return true; for(int j=L[i];j!=i;j=L[j]) resume(C[j]); //»Ö¸´ÄÇÒ»ÐÐÓÐ1µÄÁÐ } resume(c); //»Ö¸´c¶ÔÓ¦µÄÁÐ return false; }
void dlx(int k) { if(k+h()>= ans) return; if(R[head]==head) { ans = min(ans,k); return; } int s=INF,c; for(int i=R[head];i!=head;i=R[i]){ if(S[i]<s) s=S[i],c=i; } for(int i=D[c];i!=c;i=D[i]) { remove(i); for(int j=R[i];j!=i;j=R[j]) remove(j); dlx(k+1); for(int j=L[i];j!=i;j=L[j]) resume(j); resume(i); } }
bool dlx(int k){ if(R[head] == head){ return true; } int s = INF,c; for(int i = R[head];i!=head ; i = R[i]){ if(S[i] < s ) s = S[i] ,c = i; } remove(c); for(int i = D[c] ; i != c; i = D[i]){ int tt = row[i]; sudoku[ to[tt][0] ][ to[tt][1] ] = to[tt][2]; for(int f= R[i];f != i ; f = R[f]) remove(C[f]); if(dlx(k+1)) return true; for(int f= L[i]; f != i ; f = L[f]) resume(C[f]); } resume(c); return false; }
bool dlx(int k) { if(R[head]==head) { //全部填完 //输出选择了哪些行 cout << k ; for(int i=0;i<k ;i++) cout << " " << row[O[i]]; cout << endl; return true; } int s=INF,c; //找1最少的列对应的第一个1的位置i for(int i=R[head];i!=head;i=R[i]) if(S[i]<s) s=S[i],c=i; remove(c); //删除c对应的列 for(int i=D[c];i!=c;i=D[i]) { O[k]=i; for(int j=R[i];j!=i;j=R[j]) remove(C[j]); //删除那一行有1的列 if(dlx(k+1)) return true; for(int j=L[i];j!=i;j=L[j]) resume(C[j]); //恢复那一行有1的列 } resume(c); //恢复c对应的列 return false; }
void solve_sudoku(){ int ji = 0; int m = 27*9 + 81; int sh = 1,ss = 82,sk = 163,sg = 244; // 行 竖 块 init(m); for(int i = 0;i < 9;i++) for(int f = 0;f < 9;f++) for(int g = 0;g < 9;g++){ to[ji][0] = i; to[ji][1] = f; to[ji][2] = g; if(-1==sudoku[i][f] || g==sudoku[i][f]){ addnode(ji,sh+ mul(i,g)); addnode(ji,ss+ mul(f,g)); addnode(ji,sk+ mul( getkuai(i,f),g )); addnode(ji,sg+ mul(i,f)); } ji++; } dlx(0); }
void solve_sudoku(){ init(27*9 + 81); int nn = 0; for(int i = 0 ; i< 9 ;i++) for(int f = 0 ;f < 9;f++) for(int g= 0 ; g< 9; g++){ to[nn][0] = i; to[nn][1] = f; to[nn][2] = g; if(-1==sudoku[i][f] || g==sudoku[i][f]){ addnode(nn,1+mul(i,g)); addnode(nn,82+mul(f,g)); addnode(nn,163+ mul( getkuai(i,f),g) ); addnode(nn,244+ mul(i,f)); } nn++; } if(false == dlx(0)) cout << "impossible" << endl; else ans(); }
bool dlx(int k) { if(R[head]==head) { //È«²¿ÌîÍê return true; } int s=INF,c; //ÕÒ1×îÉÙµÄÁжÔÓ¦µÄµÚÒ»¸ö1µÄλÖÃi for(int i=R[head];i!=head;i=R[i]) if(S[i]<s) s=S[i],c=i; remove(c); //ɾ³ýc¶ÔÓ¦µÄÁÐ for(int i=D[c];i!=c;i=D[i]) { int num = to[row[i]][0]; int s = to[row[i]][1]; int t = to[row[i]][2]; res[num][0] = s; res[num][1] = t; for(int j=R[i];j!=i;j=R[j]) remove(C[j]); //ɾ³ýÄÇÒ»ÐÐÓÐ1µÄÁÐ if(dlx(k+1)) return true; for(int j=L[i];j!=i;j=L[j]) resume(C[j]); //»Ö¸´ÄÇÒ»ÐÐÓÐ1µÄÁÐ } resume(c); //»Ö¸´c¶ÔÓ¦µÄÁÐ return false; }
bool solve(){ init(n*d + n); int nn = 0; for(int i = 0 ; i < n ;i++) { for(int f = t[i][0]; f <= t[i][1] ;f++) for(int g = f; g<= t[i][1] ;g++){ to[nn][0] = i; to[nn][1] = f; to[nn][2] = g; addnode(nn, n*d+1+i); for(int h = 0; h < n;h++) if(1 == con[i+1][h+1] || i == h) for(int j = f;j <= g;j++) addnode(nn,mul(h,j-1)+1); nn++; } to[nn][0] = i; to[nn][1] = 0; to[nn][2] = 0; addnode(nn,n*d + 1 + i); nn++; } return dlx(0); }
Dlp Frame::dxy() const { return y() <= dlx(); } ///< xy dual plane
/* Homogenous Planes in Conformal Space */ Dlp Frame::dxz() const { return -z() <= dlx(); } ///< xz dual plane
Sudoku SudokuSolver::solve_impl(const Sudoku& sudoku, bool randomized) const { if (!sudoku.is_valid()) { throw std::runtime_error("solve(): Invalid sudoku"); } const SudokuType& type = sudoku.type(); unsigned n = type.n(); auto pack = [&](unsigned a, unsigned b) -> unsigned { return a * n + b; }; auto id_cell = [&](unsigned x, unsigned y) -> unsigned { return pack(x, y); }; auto id_col = [&](unsigned x, unsigned d) -> unsigned { return type.size() + pack(x, d); }; auto id_row = [&](unsigned y, unsigned d) -> unsigned { return 2 * type.size() + pack(y, d); }; auto id_region = [&](unsigned i, unsigned d) -> unsigned { return 3 * type.size() + pack(i, d); }; std::vector<unsigned> cell_taken(type.size()); std::vector<unsigned> col_taken(type.size()); std::vector<unsigned> row_taken(type.size()); std::vector<unsigned> region_taken(type.size()); for (unsigned i = 0; i < type.size(); ++i) { if (sudoku[i] != 0) { unsigned x = i % n; unsigned y = i / n; unsigned d = sudoku[i] - 1; ++cell_taken[pack(x, y)]; ++col_taken[pack(x, d)]; ++row_taken[pack(y, d)]; ++region_taken[pack(type.region(x, y), d)]; } } std::vector<std::vector<unsigned>> matrix; for (unsigned i = 0; i < n; ++i) { for (unsigned j = 0; j < n; ++j) { if (cell_taken[pack(i, j)]) matrix.push_back({id_cell(i, j)}); if (col_taken[pack(i, j)]) matrix.push_back({id_col(i, j)}); if (row_taken[pack(i, j)]) matrix.push_back({id_row(i, j)}); if (region_taken[pack(i, j)]) matrix.push_back({id_region(i, j)}); } } std::unordered_map<unsigned, unsigned> row_position, row_digit; for (unsigned y = 0; y < n; ++y) { for (unsigned x = 0; x < n; ++x) { for (unsigned d = 0; d < n; ++d) { if (cell_taken[pack(x, y)] || col_taken[pack(x, d)] || row_taken[pack(y, d)] || region_taken[pack(type.region(x, y), d)]) { continue; } unsigned row_index = matrix.size(); row_position[row_index] = y * n + x; row_digit[row_index] = d; matrix.push_back({ id_cell(x, y), id_col(x, d), id_row(y, d), id_region(type.region(x, y), d) }); } } } AlgorithmDLX dlx(ExactCoverProblem(4 * type.size(), matrix)); auto options = AlgorithmDLX::Options(); if (randomized) { static std::random_device rd; static auto engine = std::mt19937(rd()); options.choose_random_column = randomized; options.random_engine = &engine; } options.max_solutions = randomized ? 1 : 2; auto result = dlx.search(options); auto solutions = std::vector<Sudoku>(); for (const auto& rows : result.solutions) { Sudoku solved(sudoku); for (auto i : rows) { auto pos = row_position.find(i); if (pos != row_position.end()) { solved[pos->second] = row_digit[i] + 1; } } solutions.push_back(std::move(solved)); } if (solutions.empty()) { throw std::runtime_error("No solution"); } if (solutions.size() > 1) { throw std::runtime_error("Multiple solutions"); } return solutions[0]; }