Untitled
unknown
c_cpp
3 years ago
65 kB
10
Indexable
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <set>
#include <queue>
#include <string.h>
using namespace std;
bool linkedEdge[55][55][55][55]={0};
int Map[100][100],n,m,an,am;
vector<string> ans;
pair<int,int> start;
bool CheckLinkedEdge(int x1,int y1,int x2,int y2){
return linkedEdge[x1][y1][x2][y2] || linkedEdge[x2][y2][x1][y1];
}
void PrintGra();
class puzzle
{
public:
size_t cols, rows = 0; // of lattice
vector<vector<int>> lat; // lattice
enum edge_state
{
BAN = -1, // banned
NOT = 0, // not linked
LINKED = 1 // linked
};
vector<vector<edge_state>> hrz; // horizon link
vector<vector<edge_state>> vrt; // vertical link
vector<vector<bool>> banned_point;
size_t get_conn(const int &p_r, const int &p_c)
{
size_t conn = 0;
if (point_has_edge_up(p_r, p_c))
conn++;
if (point_has_edge_down(p_r, p_c))
conn++;
if (point_has_edge_left(p_r, p_c))
conn++;
if (point_has_edge_right(p_r, p_c))
conn++;
return conn;
}
size_t lat_edge(const int &lat_r, const int &lat_c)
{
return hrz_has_edge(lat_r, lat_c) +
hrz_has_edge(lat_r + 1, lat_c) +
vrt_has_edge(lat_r, lat_c) +
vrt_has_edge(lat_r, lat_c + 1);
}
size_t get_lat_banned_edge(const int &lat_r, const int &lat_c)
{
return (hrz[lat_r][lat_c] == BAN ? 1 : 0) +
(hrz[lat_r + 1][lat_c] == BAN ? 1 : 0) +
(vrt[lat_r][lat_c] == BAN ? 1 : 0) +
(vrt[lat_r][lat_c + 1] == BAN ? 1 : 0);
}
bool hrz_sat(const int &h_r, const int &h_c)
{
if (hrz_has_up_lat(h_r, h_c) &&
lat[h_r - 1][h_c] >= 0 &&
lat_edge(h_r - 1, h_c) > lat[h_r - 1][h_c])
return false;
if (hrz_has_down_lat(h_r, h_c) &&
lat[h_r][h_c] >= 0 &&
lat_edge(h_r, h_c) > lat[h_r][h_c])
return false;
return true;
}
bool vrt_sat(const int &v_r, const int &v_c)
{
if (vrt_has_left_lat(v_r, v_c) &&
lat[v_r][v_c - 1] >= 0 &&
lat_edge(v_r, v_c - 1) > lat[v_r][v_c - 1])
return false;
if (vrt_has_right_lat(v_r, v_c) &&
lat[v_r][v_c] >= 0 &&
lat_edge(v_r, v_c) > lat[v_r][v_c])
return false;
return true;
}
bool point_can_up(const int &p_r, const int &p_c)
{
if (p_r <= 0)
return false;
if (banned_point[p_r - 1][p_c])
return false;
if (vrt[p_r - 1][p_c] == puzzle::BAN)
return false;
return true;
}
bool point_can_down(const int &p_r, const int &p_c)
{
if (p_r >= rows)
return false;
if (banned_point[p_r + 1][p_c])
return false;
if (vrt[p_r][p_c] == puzzle::BAN)
return false;
return true;
}
bool point_can_left(const int &p_r, const int &p_c)
{
if (p_c <= 0)
return false;
if (banned_point[p_r][p_c - 1])
return false;
if (hrz[p_r][p_c - 1] == puzzle::BAN)
return false;
return true;
}
bool point_can_right(const int &p_r, const int &p_c)
{
if (p_c >= cols)
return false;
if (banned_point[p_r][p_c + 1])
return false;
if (hrz[p_r][p_c] == puzzle::BAN)
return false;
return true;
}
bool point_has_edge_up(const int &p_r, const int &p_c)
{
return point_can_up(p_r, p_c) && vrt_has_edge(p_r - 1, p_c);
}
bool point_has_edge_down(const int &p_r, const int &p_c)
{
return point_can_down(p_r, p_c) && vrt_has_edge(p_r, p_c);
}
bool point_has_edge_left(const int &p_r, const int &p_c)
{
return point_can_left(p_r, p_c) && hrz_has_edge(p_r, p_c - 1);
}
bool point_has_edge_right(const int &p_r, const int &p_c)
{
return point_can_right(p_r, p_c) && hrz_has_edge(p_r, p_c);
}
int hrz_has_edge(const int &h_r, const int &h_c)
{
return hrz[h_r][h_c] == LINKED;
}
int vrt_has_edge(const int &v_r, const int &v_c)
{
return vrt[v_r][v_c] == LINKED;
}
bool hrz_has_up_lat(const int &h_r, const int &h_c)
{
return h_r > 0;
}
bool hrz_has_down_lat(const int &h_r, const int &h_c)
{
return h_r < rows;
}
bool vrt_has_left_lat(const int &v_r, const int &v_c)
{
return v_c > 0;
}
bool vrt_has_right_lat(const int &v_r, const int &v_c)
{
return v_c < cols;
}
bool complete_lat(const int &lat_r, const int &lat_c)
{
if (lat[lat_r][lat_c] >= 0 &&
lat[lat_r][lat_c] != lat_edge(lat_r, lat_c))
return false;
else
return true;
}
bool is_fin()
{
for (size_t row = 0; row < rows; row++)
{
for (size_t col = 0; col < cols; col++)
{
if (!complete_lat(row, col))
return false;
}
}
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
if (get_conn(row, col) == 1 || get_conn(row, col) == 3)
{
return false;
}
}
}
if (is_multiple_loops())
return false;
return true;
}
bool is_correct() // During solving
{
// check lattice
for (size_t row = 0; row < rows; row++)
{
for (size_t col = 0; col < cols; col++)
{
if (lat[row][col] >= 0)
{
if (lat[row][col] < lat_edge(row, col))
return false;
if (4 - lat[row][col] < get_lat_banned_edge(row, col))
return false;
}
}
}
// check point
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
if (get_conn(row, col) == 3)
{
return false;
}
// if (get_conn(row, col) == 1)
// {
// size_t ban_edges = (point_can_up(row, col) ? 0 : 1) +
// (point_can_left(row, col) ? 0 : 1) +
// (point_can_down(row, col) ? 0 : 1) +
// (point_can_right(row, col) ? 0 : 1);
// if (ban_edges >= 3)
// return false;
// }
}
}
if (is_multiple_loops())
return false;
if (!is_even_line_out())
return false;
return true;
}
bool is_multiple_loops()
{
set<pair<int, int>> done;
size_t loops = 0;
size_t lines = 0;
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
// New point with 2 conn
// Maybe in a loop
if (get_conn(row, col) == 2 && done.find({row, col}) == done.end())
{
// Mark one loop or line (BFS)
bool is_line = false;
queue<pair<int, int>> todo;
todo.push({row, col});
do
{
const auto now = todo.front();
todo.pop();
if (done.find(now) != done.end())
{
continue;
}
done.insert(now);
if (get_conn(now.first, now.second) == 1) // is a line
{
is_line = true;
}
if (point_has_edge_up(now.first, now.second))
{
if (done.find({now.first - 1, now.second}) == done.end())
{
todo.push({now.first - 1, now.second});
}
}
if (point_has_edge_down(now.first, now.second))
{
if (done.find({now.first + 1, now.second}) == done.end())
{
todo.push({now.first + 1, now.second});
}
}
if (point_has_edge_left(now.first, now.second))
{
if (done.find({now.first, now.second - 1}) == done.end())
{
todo.push({now.first, now.second - 1});
}
}
if (point_has_edge_right(now.first, now.second))
{
if (done.find({now.first, now.second + 1}) == done.end())
{
todo.push({now.first, now.second + 1});
}
}
} while (!todo.empty());
if (is_line)
{
lines++;
}
else
{
loops++;
}
if (loops > 1)
return true;
if (loops == 1 && lines > 0)
return true;
}
}
}
return false;
}
bool is_even_line_out()
{
set<pair<int, int>> done;
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
// New point with 0 or 1 conn in one island
if (get_conn(row, col) <= 1 && done.find({row, col}) == done.end())
{
// Mark one point in this island (BFS)
set<pair<int, int>> island;
queue<pair<int, int>> todo;
size_t thread_cnt = 0;
todo.push({row, col});
do
{
const auto now = todo.front();
todo.pop();
if (island.find(now) != island.end())
{
continue;
}
island.insert(now);
if (get_conn(now.first, now.second) == 1) // a "thread"
{
thread_cnt++;
}
if (point_can_up(now.first, now.second) &&
!point_has_edge_up(now.first, now.second))
{
if (island.find({now.first - 1, now.second}) == island.end() &&
get_conn(now.first - 1, now.second) < 2)
{
todo.push({now.first - 1, now.second});
}
}
if (point_can_down(now.first, now.second) &&
!point_has_edge_down(now.first, now.second))
{
if (island.find({now.first + 1, now.second}) == island.end() &&
get_conn(now.first + 1, now.second) < 2)
{
todo.push({now.first + 1, now.second});
}
}
if (point_can_left(now.first, now.second) &&
!point_has_edge_left(now.first, now.second))
{
if (island.find({now.first, now.second - 1}) == island.end() &&
get_conn(now.first, now.second - 1) < 2)
{
todo.push({now.first, now.second - 1});
}
}
if (point_can_right(now.first, now.second) &&
!point_has_edge_right(now.first, now.second))
{
if (island.find({now.first, now.second + 1}) == island.end() &&
get_conn(now.first, now.second + 1) < 2)
{
todo.push({now.first, now.second + 1});
}
}
} while (!todo.empty());
if (thread_cnt % 2)
return false;
done.insert(island.begin(), island.end());
}
}
}
return true;
}
string to_string()
{
const auto link = "█";
const auto dot = "▪";
stringstream ss;
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
if (get_conn(row, col) > 0)
ss << link;
// else if (banned_point[row][col])
// ss << "x";
else
ss << dot;
if (col < cols)
{
if (hrz_has_edge(row, col))
ss << link;
else if (hrz[row][col] == BAN)
ss << "x";
else
ss << " ";
}
}
ss << "\n";
if (row < rows)
{
for (size_t col = 0; col <= cols; col++)
{
if (vrt_has_edge(row, col))
ss << link;
else if (vrt[row][col] == BAN)
ss << "x";
else
ss << " ";
if (col < cols)
{
if (lat[row][col] >= 0)
ss << lat[row][col];
else
ss << " ";
}
}
}
ss << "\n";
}
stringstream ssa;
ans.clear();
for (size_t row = 0; row <= rows; row++)
{
for (size_t col = 0; col <= cols; col++)
{
if (get_conn(row, col) > 0)
ssa << '_';
// else if (banned_point[row][col])
// ss << "x";
else
ssa << '.';
if (col < cols)
{
if (hrz_has_edge(row, col))
ssa << '_';
else if (hrz[row][col] == BAN)
ssa << ' ';
else
ssa << ' ';
}
}
ans.push_back(ssa.str());
ssa.str("");
if (row < rows)
{
for (size_t col = 0; col <= cols; col++)
{
if (vrt_has_edge(row, col))
ssa << '_';
else if (vrt[row][col] == BAN)
ssa << ' ';
else
ssa << ' ';
if (col < cols)
{
if (lat[row][col] >= 0)
ssa << lat[row][col];
else
ssa << ' ';
}
}
}
ans.push_back(ssa.str());
ssa.str("");
}
n=(ans.size()-1)/2;
m=ans[0].size()/2;
an=ans.size(),am=ans[0].size();
memset(linkedEdge,0,sizeof(linkedEdge));
for(int i=1;i<an;i+=2){
for(int j=1;j<am;j+=2){
if(isdigit(ans[i][j])) Map[i/2][j/2]=ans[i][j]-'0';
else Map[i/2][j/2]=-1;
}
}
start={-1,-1};
for(int i=0;i<an;i+=2){
for(int j=0;j<am;j+=2){
if(ans[i][j]=='_'){
start={i,j};
}
}
}
return ss.str();
}
};
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <set>
#include <queue>
#include <unordered_set>
class puzzle_solver
{
private:
/* data */
puzzle p;
unordered_set<string> puzzle_results;
ostream *os;
public:
void read_puzzle(istream &is);
void set_output(ostream &os)
{
this->os = &os;
}
int solve();
private:
bool heuristic(puzzle &p, bool head = true);
void ban_edge_around_zero(puzzle &p);
void prelink_around_threes(puzzle &p);
void ban_edge_around_one(puzzle &p);
void ban_edge_around_two(puzzle &p);
void ban_edge_around_three(puzzle &p);
void ban_edge_around_point(puzzle &p);
void ban_point(puzzle &p);
void link_around_one(puzzle &p);
void link_around_two(puzzle &p);
void link_around_three(puzzle &p);
void link_around_point(puzzle &p);
bool try_draw(puzzle &p);
void DFS(puzzle &p);
void go_with_line(puzzle &p,
const int &start_r, const int &start_c,
int src_p_r, int src_p_c,
int dst_p_r, int dst_p_c);
void go_without_line(puzzle &p,
const int &start_r, const int &start_c,
const int &src_p_r, const int &src_p_c,
const int &dst_p_r, const int &dst_p_c);
void draw_line(puzzle p,
const int &start_r, const int &start_c,
const int &src_p_r, const int &src_p_c,
const int &dst_p_r, const int &dst_p_c);
};
void puzzle_solver::read_puzzle(istream &is)
{
// read puzzle
string line;
while(is >> line){
p.cols=line.size();
vector<int> tmp_row;
for (size_t col = 0; col < p.cols; col++)
{
const char c = line[col];
switch (c)
{
case '0':
case '1':
case '2':
case '3':
tmp_row.push_back(c - '0');
break;
default:
tmp_row.push_back(-1);
break;
}
}
p.lat.push_back(tmp_row);
p.rows++;
}
// init connect state table
for (size_t row = 0; row < p.rows + 1; row++)
{
vector<puzzle::edge_state> tmp_row;
for (size_t col = 0; col < p.cols; col++)
{
tmp_row.push_back(puzzle::NOT);
}
p.hrz.push_back(tmp_row);
}
for (size_t row = 0; row < p.rows; row++)
{
vector<puzzle::edge_state> tmp_row;
for (size_t col = 0; col < p.cols + 1; col++)
{
tmp_row.push_back(puzzle::NOT);
}
p.vrt.push_back(tmp_row);
}
// init banned point
for (size_t row = 0; row <= p.rows; row++)
{
vector<bool> tmp_row;
for (size_t col = 0; col <= p.cols; col++)
{
tmp_row.push_back(false);
}
p.banned_point.push_back(tmp_row);
}
}
int puzzle_solver::solve()
{
ban_edge_around_zero(p);
prelink_around_threes(p);
if (heuristic(p) == false)
{
return -1;
}
// Heuristic done
if (p.is_fin() && p.is_correct())
{
// Print solution
const auto result = p.to_string();
if (puzzle_results.find(result) == puzzle_results.end())
{
puzzle_results.insert(result);
// cout << result;
PrintGra();
}
}
DFS(p);
return puzzle_results.size();
}
bool puzzle_solver::heuristic(puzzle &p, bool ahead)
{
string last_step = p.to_string();
string curr_step;
while (true)
{
ban_edge_around_one(p);
ban_edge_around_two(p);
ban_edge_around_three(p);
ban_edge_around_point(p);
ban_point(p);
link_around_point(p);
link_around_three(p);
link_around_two(p);
link_around_one(p);
if (!p.is_correct())
{
return false;
}
curr_step = p.to_string();
// run out of normal methods
if (last_step.compare(curr_step) == 0)
{
break;
}
else // normal method make sense
{
last_step = curr_step;
}
}
// look ahead
while (ahead == true)
{
if (try_draw(p) == false)
{
return false;
}
else
{
// look ahead make sense
// try normal methods again
curr_step = p.to_string();
if (last_step.compare(curr_step) == 0)
{
break;
}
last_step = curr_step;
}
}
// look head not useful
// return to DFS
return true;
}
void puzzle_solver::ban_edge_around_zero(puzzle &p)
{
/**
* . b .
* b 0 b
* . b .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 0)
{
p.hrz[row][col] = puzzle::BAN;
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
}
}
}
void puzzle_solver::prelink_around_threes(puzzle &p)
{
/**
* . l .
* 3
* b . l . b
* 3
* . l .
*/
for (size_t row = 0; row < p.rows - 1; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 3 && p.lat[row + 1][col] == 3)
{
p.hrz[row][col] = puzzle::LINKED;
p.hrz[row + 1][col] = puzzle::LINKED;
p.hrz[row + 2][col] = puzzle::LINKED;
if (p.point_can_left(row + 1, col))
p.hrz[row + 1][col - 1] = puzzle::BAN;
if (p.point_can_right(row + 1, col + 1))
p.hrz[row + 1][col + 1] = puzzle::BAN;
}
}
}
/**
* b
* . . .
* l 3 l 3 l
* . . .
* b
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols - 1; col++)
{
if (p.lat[row][col] == 3 && p.lat[row][col + 1] == 3)
{
p.vrt[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
p.vrt[row][col + 2] = puzzle::LINKED;
if (p.point_can_up(row, col + 1))
p.vrt[row - 1][col + 1] = puzzle::BAN;
if (p.point_can_down(row + 1, col + 1))
p.vrt[row + 1][col + 1] = puzzle::BAN;
}
}
}
/**
* b
* b . l . .
* l 3
* . . .
* 3 l
* . . l . b
* b
*/
for (size_t row = 0; row < p.rows - 1; row++)
{
for (size_t col = 0; col < p.cols - 1; col++)
{
if (p.lat[row][col] == 3 && p.lat[row + 1][col + 1] == 3)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
p.hrz[row + 2][col + 1] = puzzle::LINKED;
p.vrt[row + 1][col + 2] = puzzle::LINKED;
if (p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::BAN;
if (p.point_can_left(row, col))
p.hrz[row][col - 1] = puzzle::BAN;
if (p.point_can_down(row + 2, col + 2))
p.vrt[row + 2][col + 2] = puzzle::BAN;
if (p.point_can_right(row + 2, col + 2))
p.hrz[row + 2][col + 2] = puzzle::BAN;
}
}
}
/**
* b
* . . l . b
* 3 l
* . . .
* l 3
* b . l . .
* b
*/
for (size_t row = 0; row < p.rows - 1; row++)
{
for (size_t col = 0; col < p.cols - 1; col++)
{
if (p.lat[row][col + 1] == 3 && p.lat[row + 1][col] == 3)
{
p.hrz[row][col + 1] = puzzle::LINKED;
p.vrt[row][col + 2] = puzzle::LINKED;
p.hrz[row + 2][col] = puzzle::LINKED;
p.vrt[row + 1][col] = puzzle::LINKED;
if (p.point_can_up(row, col + 2))
p.vrt[row - 1][col + 2] = puzzle::BAN;
if (p.point_can_right(row, col + 2))
p.hrz[row][col + 2] = puzzle::BAN;
if (p.point_can_down(row + 2, col))
p.vrt[row + 2][col] = puzzle::BAN;
if (p.point_can_left(row + 2, col))
p.hrz[row + 2][col - 1] = puzzle::BAN;
}
}
}
}
void puzzle_solver::ban_edge_around_one(puzzle &p)
{
/**
* x
* x . b .
* b 1
* . .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 1 && p.get_lat_banned_edge(row, col) < 2)
{
if (!p.point_can_up(row, col) &&
!p.point_can_left(row, col))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
if (!p.point_can_up(row, col + 1) &&
!p.point_can_right(row, col + 1))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
if (!p.point_can_down(row + 1, col) &&
!p.point_can_left(row + 1, col))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
if (!p.point_can_down(row + 1, col + 1) &&
!p.point_can_right(row + 1, col + 1))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
}
}
}
/**
* . b .
* b 1 |
* . b .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 1 && p.get_lat_banned_edge(row, col) != 3)
{
if (p.hrz_has_edge(row, col))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.hrz_has_edge(row + 1, col))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.vrt_has_edge(row, col))
{
p.hrz[row][col] = puzzle::BAN;
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.vrt_has_edge(row, col + 1))
{
p.hrz[row][col] = puzzle::BAN;
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
}
}
}
/**
* x
* - . .
* 1 b
* . b .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 1 && p.get_lat_banned_edge(row, col) < 2)
{
if ((p.point_has_edge_up(row, col) || p.point_has_edge_left(row, col)) &&
(!p.point_can_up(row, col) || !p.point_can_left(row, col)))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
if ((p.point_has_edge_up(row, col + 1) || p.point_has_edge_right(row, col + 1)) &&
(!p.point_can_up(row, col + 1) || !p.point_can_right(row, col + 1)))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
if ((p.point_has_edge_down(row + 1, col) || p.point_has_edge_left(row + 1, col)) &&
(!p.point_can_down(row + 1, col) || !p.point_can_left(row + 1, col)))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
if ((p.point_has_edge_down(row + 1, col + 1) || p.point_has_edge_right(row + 1, col + 1)) &&
(!p.point_can_down(row + 1, col + 1) || !p.point_can_right(row + 1, col + 1)))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
}
}
}
}
void puzzle_solver::ban_edge_around_two(puzzle &p)
{
/**
* . - .
* b 2 |
* . b .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 2 && p.get_lat_banned_edge(row, col) != 2)
{
if (p.hrz_has_edge(row, col) &&
p.vrt_has_edge(row, col))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.hrz_has_edge(row, col) &&
p.hrz_has_edge(row + 1, col))
{
p.vrt[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.hrz_has_edge(row, col) &&
p.vrt_has_edge(row, col + 1))
{
p.hrz[row + 1][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
else if (p.hrz_has_edge(row + 1, col) &&
p.vrt_has_edge(row, col))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.hrz_has_edge(row + 1, col) &&
p.vrt_has_edge(row, col + 1))
{
p.hrz[row][col] = puzzle::BAN;
p.vrt[row][col] = puzzle::BAN;
}
else if (p.vrt_has_edge(row, col) &&
p.vrt_has_edge(row, col + 1))
{
p.hrz[row][col] = puzzle::BAN;
p.hrz[row + 1][col] = puzzle::BAN;
}
}
}
}
}
void puzzle_solver::ban_edge_around_three(puzzle &p)
{
/**
* . - .
* | 3 |
* . b .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 3 && p.get_lat_banned_edge(row, col) != 1)
{
if (p.hrz_has_edge(row, col) &&
p.hrz_has_edge(row + 1, col) &&
p.vrt_has_edge(row, col))
{
p.vrt[row][col + 1] = puzzle::BAN;
}
else if (p.hrz_has_edge(row, col) &&
p.hrz_has_edge(row + 1, col) &&
p.vrt_has_edge(row, col + 1))
{
p.vrt[row][col] = puzzle::BAN;
}
else if (p.vrt_has_edge(row, col) &&
p.vrt_has_edge(row, col + 1) &&
p.hrz_has_edge(row, col))
{
p.hrz[row + 1][col] = puzzle::BAN;
}
else if (p.vrt_has_edge(row, col) &&
p.vrt_has_edge(row, col + 1) &&
p.hrz_has_edge(row + 1, col))
{
p.hrz[row][col] = puzzle::BAN;
}
}
}
}
}
void puzzle_solver::ban_edge_around_point(puzzle &p)
{
/**
* x
* x . x
* b
*/
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 0; col <= p.cols; col++)
{
if (!p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
p.point_can_right(row, col))
{
p.hrz[row][col] = puzzle::BAN;
}
else if (!p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.hrz[row][col - 1] = puzzle::BAN;
}
else if (!p.point_can_up(row, col) &&
p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.vrt[row][col] = puzzle::BAN;
}
else if (p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.vrt[row - 1][col] = puzzle::BAN;
}
}
}
/**
* b
* - . b
* |
*/
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 0; col <= p.cols; col++)
{
if (p.point_has_edge_up(row, col) &&
p.point_has_edge_down(row, col))
{
if (p.point_can_left(row, col))
p.hrz[row][col - 1] = puzzle::BAN;
if (p.point_can_right(row, col))
p.hrz[row][col] = puzzle::BAN;
}
else if (p.point_has_edge_left(row, col) &&
p.point_has_edge_right(row, col))
{
if (p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::BAN;
if (p.point_can_down(row, col))
p.vrt[row][col] = puzzle::BAN;
}
else if (p.point_has_edge_up(row, col) &&
p.point_has_edge_left(row, col))
{
if (p.point_can_right(row, col))
p.hrz[row][col] = puzzle::BAN;
if (p.point_can_down(row, col))
p.vrt[row][col] = puzzle::BAN;
}
else if (p.point_has_edge_up(row, col) &&
p.point_has_edge_right(row, col))
{
if (p.point_can_left(row, col))
p.hrz[row][col - 1] = puzzle::BAN;
if (p.point_can_down(row, col))
p.vrt[row][col] = puzzle::BAN;
}
else if (p.point_has_edge_down(row, col) &&
p.point_has_edge_left(row, col))
{
if (p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::BAN;
if (p.point_can_right(row, col))
p.hrz[row][col] = puzzle::BAN;
}
else if (p.point_has_edge_down(row, col) &&
p.point_has_edge_right(row, col))
{
if (p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::BAN;
if (p.point_can_left(row, col))
p.hrz[row][col - 1] = puzzle::BAN;
}
}
}
}
void puzzle_solver::ban_point(puzzle &p)
{
/**
* x
* x b x
* x
*/
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 0; col <= p.cols; col++)
{
if (!p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.banned_point[row][col] = true;
}
}
}
}
void puzzle_solver::link_around_one(puzzle &p)
{
/**
* . x .
* x 1 x
* . l .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 1 &&
!p.complete_lat(row, col) &&
p.get_lat_banned_edge(row, col) == 3)
{
if (p.hrz[row][col] != puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
}
else if (p.hrz[row + 1][col] != puzzle::BAN)
{
p.hrz[row + 1][col] = puzzle::LINKED;
}
else if (p.vrt[row][col] != puzzle::BAN)
{
p.vrt[row][col] = puzzle::LINKED;
}
else if (p.vrt[row][col + 1] != puzzle::BAN)
{
p.vrt[row][col + 1] = puzzle::LINKED;
}
}
}
}
}
void puzzle_solver::link_around_two(puzzle &p)
{
/**
* . l .
* x 2 x
* . l .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 2 &&
!p.complete_lat(row, col) &&
p.get_lat_banned_edge(row, col) == 2)
{
if (p.hrz[row][col] == puzzle::BAN &&
p.hrz[row + 1][col] == puzzle::BAN)
{
p.vrt[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.vrt[row][col] == puzzle::BAN &&
p.vrt[row][col + 1] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.hrz[row + 1][col] = puzzle::LINKED;
}
else if (p.hrz[row][col] == puzzle::BAN &&
p.vrt[row][col] == puzzle::BAN)
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.hrz[row][col] == puzzle::BAN &&
p.vrt[row][col + 1] == puzzle::BAN)
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
else if (p.hrz[row + 1][col] == puzzle::BAN &&
p.vrt[row][col] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.hrz[row + 1][col] == puzzle::BAN &&
p.vrt[row][col + 1] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
}
}
}
/**
* ?
* . . ?
* 2
* ? . . x
* ? x
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 2 &&
!p.complete_lat(row, col))
{
if (!p.point_can_up(row, col) && !p.point_can_left(row, col))
{
if (!p.point_can_left(row + 1, col) && p.point_can_down(row + 1, col))
p.vrt[row + 1][col] = puzzle::LINKED;
if (p.point_can_left(row + 1, col) && !p.point_can_down(row + 1, col))
p.hrz[row + 1][col - 1] = puzzle::LINKED;
if (!p.point_can_right(row, col + 1) && p.point_can_up(row, col + 1))
p.vrt[row - 1][col + 1] = puzzle::LINKED;
if (p.point_can_right(row, col + 1) && !p.point_can_up(row, col + 1))
p.hrz[row][col + 1] = puzzle::LINKED;
}
if (!p.point_can_up(row, col + 1) && !p.point_can_right(row, col + 1))
{
if (!p.point_can_left(row, col) && p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::LINKED;
if (p.point_can_left(row, col) && !p.point_can_up(row, col))
p.hrz[row][col - 1] = puzzle::LINKED;
if (!p.point_can_right(row + 1, col + 1) && p.point_can_down(row + 1, col + 1))
p.vrt[row + 1][col + 1] = puzzle::LINKED;
if (p.point_can_right(row + 1, col + 1) && !p.point_can_down(row + 1, col + 1))
p.hrz[row + 1][col + 1] = puzzle::LINKED;
}
if (!p.point_can_down(row + 1, col + 1) && !p.point_can_right(row + 1, col + 1))
{
if (!p.point_can_right(row, col + 1) && p.point_can_up(row, col + 1))
p.vrt[row - 1][col + 1] = puzzle::LINKED;
if (p.point_can_right(row, col + 1) && !p.point_can_up(row, col + 1))
p.hrz[row][col + 1] = puzzle::LINKED;
if (!p.point_can_left(row + 1, col) && p.point_can_down(row + 1, col))
p.vrt[row + 1][col] = puzzle::LINKED;
if (p.point_can_left(row + 1, col) && !p.point_can_down(row + 1, col))
p.hrz[row + 1][col - 1] = puzzle::LINKED;
}
if (!p.point_can_down(row + 1, col) && !p.point_can_left(row + 1, col))
{
if (!p.point_can_left(row, col) && p.point_can_up(row, col))
p.vrt[row - 1][col] = puzzle::LINKED;
if (p.point_can_left(row, col) && !p.point_can_up(row, col))
p.hrz[row][col - 1] = puzzle::LINKED;
if (!p.point_can_right(row + 1, col + 1) && p.point_can_down(row + 1, col + 1))
p.vrt[row + 1][col + 1] = puzzle::LINKED;
if (p.point_can_right(row + 1, col + 1) && !p.point_can_down(row + 1, col + 1))
p.hrz[row + 1][col + 1] = puzzle::LINKED;
}
}
}
}
}
void puzzle_solver::link_around_three(puzzle &p)
{
/**
* . l .
* x 3 l
* . l .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 3 &&
!p.complete_lat(row, col) &&
p.get_lat_banned_edge(row, col) == 1)
{
if (p.hrz[row][col] == puzzle::BAN)
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.hrz[row + 1][col] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.vrt[row][col] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
else if (p.vrt[row][col + 1] == puzzle::BAN)
{
p.hrz[row][col] = puzzle::LINKED;
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
}
}
}
/**
* x
* x . l .
* l 3
* . .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 3 && !p.complete_lat(row, col))
{
if (!p.point_can_up(row, col) &&
!p.point_can_left(row, col))
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
if (!p.point_can_up(row, col + 1) &&
!p.point_can_right(row, col + 1))
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
if (!p.point_can_down(row + 1, col) &&
!p.point_can_left(row + 1, col))
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
if (!p.point_can_down(row + 1, col + 1) &&
!p.point_can_right(row + 1, col + 1))
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
}
}
}
/**
* - . .
* 3 l
* . l .
*/
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 0; col < p.cols; col++)
{
if (p.lat[row][col] == 3 && !p.complete_lat(row, col))
{
if (p.point_has_edge_up(row, col) ||
p.point_has_edge_left(row, col))
{
if (p.hrz[row + 1][col] == puzzle::NOT &&
p.vrt[row][col + 1] == puzzle::NOT)
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
}
if (p.point_has_edge_up(row, col + 1) ||
p.point_has_edge_right(row, col + 1))
{
if (p.hrz[row + 1][col] == puzzle::NOT &&
p.vrt[row][col] == puzzle::NOT)
{
p.hrz[row + 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
}
if (p.point_has_edge_down(row + 1, col) ||
p.point_has_edge_left(row + 1, col))
{
if (p.hrz[row][col] == puzzle::NOT &&
p.vrt[row][col + 1] == puzzle::NOT)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col + 1] = puzzle::LINKED;
}
}
if (p.point_has_edge_down(row + 1, col + 1) ||
p.point_has_edge_right(row + 1, col + 1))
{
if (p.hrz[row][col] == puzzle::NOT &&
p.vrt[row][col] == puzzle::NOT)
{
p.hrz[row][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
}
}
}
}
}
void puzzle_solver::link_around_point(puzzle &p)
{
/**
* x
* l . x
* |
*/
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 0; col <= p.cols; col++)
{
if (p.get_conn(row, col) == 1)
{
if (p.point_can_up(row, col) &&
p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.vrt[row - 1][col] = puzzle::LINKED;
p.vrt[row][col] = puzzle::LINKED;
}
else if (p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.vrt[row - 1][col] = puzzle::LINKED;
p.hrz[row][col - 1] = puzzle::LINKED;
}
else if (p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
p.point_can_right(row, col))
{
p.vrt[row - 1][col] = puzzle::LINKED;
p.hrz[row][col] = puzzle::LINKED;
}
else if (!p.point_can_up(row, col) &&
p.point_can_down(row, col) &&
p.point_can_left(row, col) &&
!p.point_can_right(row, col))
{
p.vrt[row][col] = puzzle::LINKED;
p.hrz[row][col - 1] = puzzle::LINKED;
}
else if (!p.point_can_up(row, col) &&
p.point_can_down(row, col) &&
!p.point_can_left(row, col) &&
p.point_can_right(row, col))
{
p.vrt[row][col] = puzzle::LINKED;
p.hrz[row][col] = puzzle::LINKED;
}
else if (!p.point_can_up(row, col) &&
!p.point_can_down(row, col) &&
p.point_can_left(row, col) &&
p.point_can_right(row, col))
{
p.hrz[row][col - 1] = puzzle::LINKED;
p.hrz[row][col] = puzzle::LINKED;
}
}
}
}
}
bool puzzle_solver::try_draw(puzzle &p)
{
// horizontal
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 1; col < p.cols; col++)
{
if (p.hrz[row][col] == puzzle::NOT)
{
puzzle np = p;
bool no_link = false;
bool no_ban = false;
np.hrz[row][col] = puzzle::BAN;
if (heuristic(np, false) == false)
{
no_ban = true;
}
np = p;
np.hrz[row][col] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
no_link = true;
}
if (no_link && no_ban)
{
return false;
}
else if (no_link)
{
p.hrz[row][col] = puzzle::BAN;
heuristic(p, false);
}
else if (no_ban)
{
p.hrz[row][col] = puzzle::LINKED;
heuristic(p, false);
}
}
}
}
// vertical
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 1; col <= p.cols; col++)
{
if (p.vrt[row][col] == puzzle::NOT)
{
puzzle np = p;
bool no_link = false;
bool no_ban = false;
np.vrt[row][col] = puzzle::BAN;
if (heuristic(np, false) == false)
{
no_ban = true;
}
np = p;
np.vrt[row][col] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
no_link = true;
}
if (no_link && no_ban)
{
return false;
}
else if (no_link)
{
p.vrt[row][col] = puzzle::BAN;
heuristic(p, false);
}
else if (no_ban)
{
p.vrt[row][col] = puzzle::LINKED;
heuristic(p, false);
}
}
}
}
// around two
for (size_t row = 0; row < p.rows; row++)
{
for (size_t col = 1; col < p.cols; col++)
{
if (p.lat[row][col] == 2 &&
p.lat_edge(row, col) == 0 &&
p.get_lat_banned_edge(row, col) == 0)
{
puzzle np = p;
int not_allow[6][4] = {0};
np.hrz[row][col] = puzzle::LINKED;
np.vrt[row][col] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[0][0] = -1;
not_allow[0][1] = -1;
not_allow[0][2] = 1;
not_allow[0][3] = 1;
}
np = p;
np.hrz[row][col] = puzzle::LINKED;
np.vrt[row][col + 1] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[1][0] = 1;
not_allow[1][1] = -1;
not_allow[1][2] = -1;
not_allow[1][3] = 1;
}
np = p;
np.hrz[row + 1][col] = puzzle::LINKED;
np.vrt[row][col + 1] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[2][0] = 1;
not_allow[2][1] = 1;
not_allow[2][2] = -1;
not_allow[2][3] = -1;
}
np = p;
np.hrz[row + 1][col] = puzzle::LINKED;
np.vrt[row][col] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[3][0] = -1;
not_allow[3][1] = 1;
not_allow[3][2] = 1;
not_allow[3][3] = -1;
}
np = p;
np.hrz[row][col] = puzzle::LINKED;
np.hrz[row + 1][col] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[4][0] = 1;
not_allow[4][1] = -1;
not_allow[4][2] = 1;
not_allow[4][3] = -1;
}
np = p;
np.vrt[row][col] = puzzle::LINKED;
np.vrt[row][col + 1] = puzzle::LINKED;
if (heuristic(np, false) == false)
{
not_allow[5][0] = -1;
not_allow[5][1] = 1;
not_allow[5][2] = -1;
not_allow[5][3] = 1;
}
int no_cnt[4] = {0};
int link_cnt[4] = {0};
for (size_t i = 0; i < 6; i++)
{
for (size_t j = 0; j < 4; j++)
{
no_cnt[j] += (not_allow[i][j] == -1 ? 1 : 0);
link_cnt[j] += (not_allow[i][j] == 1 ? 1 : 0);
}
}
if (no_cnt[0] == 3)
{
p.vrt[row][col] = puzzle::BAN;
}
if (no_cnt[1] == 3)
{
p.hrz[row][col] = puzzle::BAN;
}
if (no_cnt[2] == 3)
{
p.vrt[row][col + 1] = puzzle::BAN;
}
if (no_cnt[3] == 3)
{
p.hrz[row + 1][col] = puzzle::BAN;
}
if (link_cnt[0] == 3)
{
p.vrt[row][col] = puzzle::LINKED;
}
if (link_cnt[1] == 3)
{
p.hrz[row][col] = puzzle::LINKED;
}
if (link_cnt[2] == 3)
{
p.vrt[row][col + 1] = puzzle::LINKED;
}
if (link_cnt[3] == 3)
{
p.hrz[row + 1][col] = puzzle::LINKED;
}
heuristic(p, false);
}
}
}
return true;
}
void puzzle_solver::DFS(puzzle &p)
{
// Start with one line
for (size_t row = 0; row <= p.rows; row++)
{
for (size_t col = 1; col <= p.cols; col++)
{
if (!p.banned_point[row][col] && p.get_conn(row, col) == 1)
{
go_without_line(p, row, col, row, col, row, col);
return;
}
}
}
// No line on this map
// For every points find all solutions
for (size_t row = 0; row <= p.rows; row++)
{
// Optimized
for (size_t col = 1; col <= p.cols; col += 2)
{
go_without_line(p, row, col, row, col, row, col);
// set point banned
p.banned_point[row][col - 1] = true;
p.banned_point[row][col] = true;
if (col + 1 == p.cols)
p.banned_point[row][col + 1] = true;
}
}
}
void puzzle_solver::go_with_line(puzzle &p,
const int &start_r, const int &start_c,
int src_p_r, int src_p_c,
int dst_p_r, int dst_p_c)
{
while (p.get_conn(dst_p_r, dst_p_c) == 2) // with line
{
// If solved
if (dst_p_r == start_r && dst_p_c == start_c)
{
// Do final check
if (p.is_fin() && p.is_correct())
{
// Print solution
const auto result = p.to_string();
if (puzzle_results.find(result) == puzzle_results.end())
{
puzzle_results.insert(result);
// cout << result;
PrintGra();
}
}
return;
}
// one step
if (p.point_can_up(dst_p_r, dst_p_c) &&
p.vrt_has_edge(dst_p_r - 1, dst_p_c) &&
dst_p_r - 1 != src_p_r)
{
src_p_r = dst_p_r;
src_p_c = dst_p_c;
--dst_p_r;
}
else if (p.point_can_down(dst_p_r, dst_p_c) &&
p.vrt_has_edge(dst_p_r, dst_p_c) &&
dst_p_r + 1 != src_p_r)
{
src_p_r = dst_p_r;
src_p_c = dst_p_c;
++dst_p_r;
}
else if (p.point_can_left(dst_p_r, dst_p_c) &&
p.hrz_has_edge(dst_p_r, dst_p_c - 1) &&
dst_p_c - 1 != src_p_c)
{
src_p_r = dst_p_r;
src_p_c = dst_p_c;
--dst_p_c;
}
else if (p.point_can_right(dst_p_r, dst_p_c) &&
p.hrz_has_edge(dst_p_r, dst_p_c) &&
dst_p_c + 1 != src_p_c)
{
src_p_r = dst_p_r;
src_p_c = dst_p_c;
++dst_p_c;
}
}
// without line
go_without_line(p,
start_r, start_c,
src_p_r, src_p_c,
dst_p_r, dst_p_c);
}
void puzzle_solver::go_without_line(puzzle &p,
const int &start_r, const int &start_c,
const int &src_p_r, const int &src_p_c,
const int &dst_p_r, const int &dst_p_c)
{
if (p.point_can_up(dst_p_r, dst_p_c) &&
p.vrt[dst_p_r - 1][dst_p_c] == puzzle::NOT) // try draw up
{
draw_line(p,
start_r, start_c,
dst_p_r, dst_p_c,
dst_p_r - 1, dst_p_c);
}
if (p.point_can_down(dst_p_r, dst_p_c) &&
p.vrt[dst_p_r][dst_p_c] == puzzle::NOT) // try draw down
{
draw_line(p,
start_r, start_c,
dst_p_r, dst_p_c,
dst_p_r + 1, dst_p_c);
}
if (p.point_can_left(dst_p_r, dst_p_c) &&
p.hrz[dst_p_r][dst_p_c - 1] == puzzle::NOT) // try draw left
{
draw_line(p,
start_r, start_c,
dst_p_r, dst_p_c,
dst_p_r, dst_p_c - 1);
}
if (p.point_can_right(dst_p_r, dst_p_c) &&
p.hrz[dst_p_r][dst_p_c] == puzzle::NOT) // try draw right
{
draw_line(p,
start_r, start_c,
dst_p_r, dst_p_c,
dst_p_r, dst_p_c + 1);
}
}
void puzzle_solver::draw_line(puzzle p,
const int &start_r, const int &start_c,
const int &src_p_r, const int &src_p_c,
const int &dst_p_r, const int &dst_p_c)
{
if (src_p_r == dst_p_r) // previous go horizontally
{
int h_r, h_c;
if (src_p_c > dst_p_c) // previous go left
{
h_r = dst_p_r;
h_c = dst_p_c;
}
else // previous go right
{
h_r = src_p_r;
h_c = src_p_c;
}
// Draw line
p.hrz[h_r][h_c] = puzzle::LINKED;
// Check lattice
if (!p.hrz_sat(h_r, h_c))
return;
}
else // previous go vertically
{
int v_r, v_c;
if (src_p_r > dst_p_r) // previous go up
{
v_r = dst_p_r;
v_c = dst_p_c;
}
else // previous go down
{
v_r = src_p_r;
v_c = src_p_c;
}
// Draw line
p.vrt[v_r][v_c] = puzzle::LINKED;
// Check lattice
if (!p.vrt_sat(v_r, v_c))
return;
}
// Check connectivity
if (p.get_conn(dst_p_r, dst_p_c) > 2 || p.get_conn(dst_p_r, dst_p_c) == 0)
return;
// Do heuristic
if (heuristic(p) == false)
return;
// If solved
if (dst_p_r == start_r && dst_p_c == start_c)
{
// Do final check
if (p.is_fin() && p.is_correct())
{
// Print solution
const auto result = p.to_string();
if (puzzle_results.find(result) == puzzle_results.end())
{
puzzle_results.insert(result);
// cout << result;
PrintGra();
}
}
return;
}
// Go next point
if (p.get_conn(dst_p_r, dst_p_c) == 2)
{
go_with_line(p, start_r, start_c, src_p_r, src_p_c, dst_p_r, dst_p_c);
}
else // 1
{
go_without_line(p, start_r, start_c, src_p_r, src_p_c, dst_p_r, dst_p_c);
}
}
void PrintGra(){
int x=start.first,y=start.second;
pair<int,int> pre={x,y};
int cnt=0;
do{
if(x+1<an && ans[x+1][y]=='_' && make_pair(x+2,y)!=pre){
linkedEdge[x/2][y/2][x/2+1][y/2]=true;
linkedEdge[x/2+1][y/2][x/2][y/2]=true;
pre={x,y};
x+=2;
}else if(x-1>=0 && ans[x-1][y]=='_' && make_pair(x-2,y)!=pre){
linkedEdge[x/2][y/2][x/2-1][y/2]=true;
linkedEdge[x/2-1][y/2][x/2][y/2]=true;
pre={x,y};
x-=2;
}else if(y+1<am && ans[x][y+1]=='_' && make_pair(x,y+2)!=pre){
linkedEdge[x/2][y/2][x/2][y/2+1]=true;
linkedEdge[x/2][y/2+1][x/2][y/2]=true;
pre={x,y};
y+=2;
}else if(y-1>=0 && ans[x][y-1]=='_' && make_pair(x,y-2)!=pre){
linkedEdge[x/2][y/2][x/2][y/2-1]=true;
linkedEdge[x/2][y/2-1][x/2][y/2]=true;
pre={x,y};
y-=2;
}
}while(make_pair(x,y)!=start);
for(int i=0;i<m;i++){
cout << "." << (CheckLinkedEdge(0,i,0,i+1)?"___":" ");
}
cout << ".\n";
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout << (CheckLinkedEdge(i,j,i+1,j)?'|':' ') << ' ' << (Map[i][j]!=-1?char(Map[i][j]+'0'):' ') << ' ';
}
cout << (CheckLinkedEdge(i,m,i+1,m)?'|':' ') << '\n';
for(int j=0;j<m;j++){
cout << (CheckLinkedEdge(i,j,i+1,j)?'!':'.') << (CheckLinkedEdge(i+1,j,i+1,j+1)?"___":" ");
}
cout << (CheckLinkedEdge(i+1,m,i,m)?'!':'.') << '\n';
}
}
int main(int argc, char **argv)
{
ifstream puzzle_file(argv[1]);
puzzle_solver ps;
ps.read_puzzle(puzzle_file);
ps.solve();
return 0;
}Editor is loading...