课堂作业-N皇后算法
2019/09
01
16:09
#include <stdio.h>
#include <tchar.h>
#include <vector>
#include <stack>
#include <string>
#include <algorithm>
#include <windows.h>
#include "mmsystem.h"
#pragma comment(lib, "winmm.lib")
class ntbase
{
public:
static const char* tostr(int i)
{
static char buff[32];
sprintf_s(buff, "%d", i);
return buff;
}
static const char* tostr(unsigned int i)
{
static char buff[32];
sprintf_s(buff, "%d", i);
return buff;
}
static const char* tostr2d(unsigned int i)
{
static char buff[32];
sprintf_s(buff, "%02d", i);
return buff;
}
};
template<typename T>
struct ntpos_t
{
ntpos_t(T a, T b):x(a), y(b) {}
ntpos_t():x(0), y(0) {}
T x, y;
};
typedef ntpos_t<unsigned int> ntpos_ui;
typedef std::vector<ntpos_ui> ntpos_v1;
typedef std::vector<ntpos_v1> ntpos_v2;
enum { FORCE_DIR= 4 };
template<unsigned int SIZE>
struct ntpos_stack_uz
{
ntpos_stack_uz()
: usize(0)
, log_enable(false)
{
}
ntpos_ui pos[SIZE];
unsigned int usize;
void push(unsigned int ax, unsigned int ay)
{
pos[usize].x = ax;
pos[usize].y = ay;
++usize;
if (log_enable)
{
for(unsigned int i=0; i<usize-1; ++i)
{
log_content+= " ";
}
char buff[256];
sprintf_s(buff, ">%d,%d\n", ax, ay);
log_content += buff;
}
}
void pop()
{
if (usize> 0)
{
--usize;
if (log_enable)
{
for(unsigned int i=0; i<usize; ++i)
{
log_content+= " ";
}
char buff[256];
sprintf_s(buff, "<%d,%d\n", pos[usize].x, pos[usize].y);
log_content += buff;
}
}
}
unsigned int size() const
{
return usize;
}
bool log_enable;
std::string log_content;
};
template<unsigned int D1SIZE>
struct flag_1d
{
flag_1d(): size(0) {}
ntpos_ui pos[D1SIZE];
unsigned int size;
void add(unsigned int x, unsigned int y)
{
pos[size].x = x;
pos[size].y = y;
++size;
}
};
template<unsigned int D1SIZE, unsigned int D2SIZE>
struct flag_2d
{
flag_1d<D1SIZE> lines[D2SIZE];
enum { SIZE = D2SIZE };
void clear()
{
for(unsigned int i=0; i<D2SIZE; ++i)
{
lines[i].size = 0;
}
}
};
template <unsigned int BOUND_SIZE>
struct influence_range
{
influence_range()
{
memset(this, 0, sizeof(*this));
}
typedef flag_2d<BOUND_SIZE, FORCE_DIR> force_flag_2d;
force_flag_2d inf_range[BOUND_SIZE][BOUND_SIZE];
};
template <unsigned int BOUND_SIZE>
struct force_range
{
force_range()
{
memset(this, 0, sizeof(*this));
}
void add_force(unsigned int y, unsigned int x)
{
++force[y][x];
}
void dec_force(unsigned int y, unsigned int x)
{
--force[y][x];
}
int at(unsigned int y, unsigned int x) const
{
return force[y][x];
}
int is_empty(unsigned int y, unsigned int x) const
{
return at(y, x) == 0;
}
int force[BOUND_SIZE][BOUND_SIZE];
};
struct force_obj
{
force_obj(unsigned int acod, unsigned int maxy): cod(acod), max_y(maxy) {}
unsigned int cod;
unsigned int max_y;
};
typedef std::vector<force_obj> force_objs;
inline bool operator < ( const force_obj& a, const force_obj& b)
{
return a.max_y < b.max_y;
}
template<typename QUEEN_OBJECT, unsigned int A_BOUND_SIZE>
struct ntqueen
{
enum { BOUND_SIZE=A_BOUND_SIZE };
typedef ntpos_stack_uz<BOUND_SIZE> queen_stack;
typedef flag_2d<BOUND_SIZE, FORCE_DIR> force_flag_2d;
typedef flag_1d<BOUND_SIZE> force_flag_1d;
typedef force_range<BOUND_SIZE> queen_range;
typedef influence_range<BOUND_SIZE> queen_inf_range;
typedef QUEEN_OBJECT bound_t[BOUND_SIZE][BOUND_SIZE];
bound_t bound;
queen_inf_range influences;
ntqueen()
{
memset(this, 0, sizeof(*this));
_build_influences(influences);
}
void _build_inf_ele(unsigned int x, unsigned int y, force_flag_2d& out) const
{
unsigned int idx= 0;
out.clear();
for(int ax=0; ax<BOUND_SIZE; ++ax)
{
if (ax != x)
{
out.lines[idx].add(ax, y);
}
}
++idx;
for(int ay=0; ay<BOUND_SIZE; ++ay)
{
if (ay!= y)
{
out.lines[idx].add(x, ay);
}
}
++idx;
for(int ax=x+1, ay=y+1; ax<BOUND_SIZE && ay<BOUND_SIZE; ++ax, ++ay)
{
out.lines[idx].add(ax, ay);
}
for(int ax=x+1, ay=y-1; ax<BOUND_SIZE && ay>=0; ++ax, --ay)
{
out.lines[idx].add(ax, ay);
}
++idx;
for(int ax=x-1, ay=y+1; ax>=0 && ay<BOUND_SIZE; --ax, ++ay)
{
out.lines[idx].add(ax, ay);
}
for(int ax=x-1, ay=y-1; ax>=0 && ay>=0; --ax, --ay)
{
out.lines[idx].add(ax, ay);
}
}
void _build_influences(queen_inf_range& infrange)
{
for(unsigned int y=0; y<BOUND_SIZE; ++y)
{
for(unsigned int x=0; x<BOUND_SIZE; ++x)
{
_build_inf_ele(x, y, infrange.inf_range[y][x]);
}
}
}
const force_flag_2d& get_influence(unsigned int y, unsigned int x) const
{
return influences.inf_range[y][x];
}
//////////////////////////////////////////////////////////////////////////
bool layout_unique_v3(queen_stack& tk, queen_range& record, int sy=0)
{
size_t size = tk.size();
for(unsigned int y=sy; y<BOUND_SIZE; ++y)
{
force_objs objs;
objs.reserve(BOUND_SIZE);
for(unsigned int x=0; x<BOUND_SIZE; ++x)
{
if (!record.is_empty(y, x))
{
continue;
}
if (! put_test(y, x))
{
continue;
}
const force_flag_2d& flag2d= get_influence(y, x);
unsigned int num= get_max_line(flag2d);
objs.push_back(force_obj(x, num));
}
if (objs.empty())
{
continue;
}
std::sort(objs.begin(), objs.end());
for(unsigned int i=0; i<objs.size(); ++i)
{
unsigned int x = objs[i].cod;
tk.push(x, y);
set(y, x, create_entity());
add_force_to_range(y, x, record);
if ( tk.size() == BOUND_SIZE)
{
return true;
}
if (!layout_unique_v3(tk, record, sy+1))
{
set(y, x, create_empty());
tk.pop();
dec_force_to_range(y, x, record);
}
else
{
if ( tk.size() == BOUND_SIZE)
{
return true;
}
}
}
}
return tk.size() > size;
}
queen_stack layout_queen_v3()
{
queen_stack r;
//r.log_enable= true;
queen_range record;
layout_unique_v3(r, record);
return r;
}
//////////////////////////////////////////////////////////////////////////
void add_force_to_range(unsigned int y, unsigned int x, queen_range& record)
{
const force_flag_2d& out= get_influence(y, x);
for(unsigned int i=0; i<out.SIZE; ++i)
{
for(unsigned int j=0; j<out.lines[i].size; ++j)
{
const ntpos_ui& pos= out.lines[i].pos[j];
record.add_force(pos.y, pos.x);
}
}
record.add_force(y, x);
}
void dec_force_to_range(unsigned int y, unsigned int x, queen_range& record)
{
const force_flag_2d& out= get_influence(y, x);
for(unsigned int i=0; i<out.SIZE; ++i)
{
for(unsigned int j=0; j<out.lines[i].size; ++j)
{
const ntpos_ui& pos= out.lines[i].pos[j];
record.dec_force(pos.y, pos.x);
}
}
record.dec_force(y, x);
}
bool layout_unique_v2(queen_stack& tk, queen_range& record)
{
size_t size = tk.size();
for(unsigned int y=0; y<BOUND_SIZE; ++y)
{
for(unsigned int x=0; x<BOUND_SIZE; ++x)
{
if (!record.is_empty(y, x))
{
continue;
}
if (! put_test(y, x))
{
continue;
}
tk.push(x, y);
set(y, x, create_entity());
add_force_to_range(y, x, record);
if ( tk.size() == BOUND_SIZE)
{
return true;
}
if (!layout_unique_v2(tk, record))
{
set(y, x, create_empty());
tk.pop();
dec_force_to_range(y, x, record);
}
else
{
if ( tk.size() == BOUND_SIZE)
{
return true;
}
}
}
}
return tk.size() > size;
}
queen_stack layout_queen_v2()
{
queen_stack r;
queen_range record;
layout_unique_v2(r, record);
return r;
}
//////////////////////////////////////////////////////////////////////////
bool layout_unique_v1(queen_stack& tk)
{
size_t size = tk.size();
for(unsigned int y=0; y<BOUND_SIZE; ++y)
{
for(unsigned int x=0; x<BOUND_SIZE; ++x)
{
if (! put_test(y, x))
{
continue;
}
tk.push(x, y);
set(y, x, create_entity());
if ( tk.size() == BOUND_SIZE)
{
return true;
}
if (!layout_unique_v1(tk))
{
set(y, x, create_empty());
tk.pop();
}
}
}
return tk.size() > size;
}
queen_stack layout_queen_v1()
{
queen_stack r;
layout_unique_v1(r);
return r;
}
bool put_test(unsigned int y, unsigned int x) const
{
if (!is_empty_pos(y, x))
{
return false;
}
if (!is_valid())
{
return false;
}
ntqueen<QUEEN_OBJECT, BOUND_SIZE> obj(*this);
obj.set(y, x, create_entity() );
return obj.is_valid();
}
//////////////////////////////////////////////////////////////////////////
bool is_emtpy_element(const QUEEN_OBJECT& v) const
{
return v.is_empty();
}
QUEEN_OBJECT create_entity() const
{
return QUEEN_OBJECT::create_entity();
}
QUEEN_OBJECT create_empty() const
{
return QUEEN_OBJECT::create_empty();
}
//////////////////////////////////////////////////////////////////////////
void print_element(const QUEEN_OBJECT& v)
{
printf("%d", v);
}
void _sprint_element(std::string& str, const QUEEN_OBJECT& v)
{
str += v.to_str();
}
bool is_empty_pos(unsigned int y, unsigned int x) const
{
return is_emtpy_element( get(y, x) );
}
unsigned int get_max_line(const force_flag_2d& lineobj) const
{
unsigned int max_y = 0;
for( unsigned int i=2; i<FORCE_DIR; ++i)
{
const force_flag_1d& d1 = lineobj.lines[i];
for(unsigned int j= 0; j<d1.size; ++j)
{
if (max_y < d1.pos[j].y)
{
max_y = d1.pos[j].y;
}
}
}
return max_y;
}
unsigned int counter_force(const force_flag_2d& lineobj) const
{
unsigned int f= 0;
for( unsigned int i=0; i<FORCE_DIR; ++i)
{
const force_flag_1d& curr= lineobj.lines[i];
for(unsigned int j=0; j<curr.size; ++j)
{
if (!is_empty_pos(curr.pos[j].y, curr.pos[j].x))
{
++f;
}
}
}
return f;
}
bool is_valid() const
{
for(unsigned int y= 0; y< BOUND_SIZE; ++y)
{
for(unsigned int x=0; x< BOUND_SIZE; ++x)
{
if (is_empty_pos(y, x))
{
continue;
}
const force_flag_2d& out= get_influence(y, x);
if (counter_force(out) > 0)
{
return false;
}
}
}
return true;
}
const QUEEN_OBJECT& get(unsigned int y, unsigned int x) const
{
return bound[y][x];
}
void set(unsigned int y, unsigned int x, const QUEEN_OBJECT& v)
{
bound[y][x]= v;
}
void _sprint_head(std::string& str)
{
str += " ";
for(unsigned int i=0; i<BOUND_SIZE; ++i)
{
str+= ntbase::tostr(i);
str+= " ";
}
str += "\n ┌";
for(unsigned int i=0; i<BOUND_SIZE; ++i)
{
str+= "─";
}
str += "┐\n";
}
void _sprint_cont(std::string& str)
{
for(unsigned int y=0; y<BOUND_SIZE; ++y)
{
str += ntbase::tostr2d(y);
str += "│";
for(unsigned int x=0; x<BOUND_SIZE; ++x)
{
const QUEEN_OBJECT& element= get(y, x);
_sprint_element(str, element);
str += " ";
}
str += "│\n";
}
}
void _sprint_end(std::string& str)
{
str += " └";
for(unsigned int i=0; i<BOUND_SIZE; ++i)
{
str+= "─";
}
str += "┘\n";
}
void view()
{
std::string str;
_sprint_head(str);
_sprint_cont(str);
_sprint_end(str);
printf(str.c_str());
}
};
struct chess_piece
{
enum
{
EMPTY = 0,
ENTITY= 1,
};
int piece_data;
chess_piece(): piece_data(EMPTY) {}
chess_piece(int d): piece_data(d) {}
bool is_empty() const { return piece_data== EMPTY; }
bool operator == ( const chess_piece& obj)
{
return obj.piece_data == piece_data;
}
const char* to_str() const
{
return ntbase::tostr(piece_data);
}
static chess_piece create_empty()
{
return chess_piece(EMPTY);
}
static chess_piece create_entity()
{
return chess_piece(ENTITY);
}
};
int main(int argc, _TCHAR* argv[])
{
unsigned long t2= timeGetTime();
typedef ntqueen<chess_piece, 8> queen11;
queen11 obj;
queen11::queen_stack k= obj.layout_queen_v3();
obj.view();
unsigned long t3= timeGetTime();
printf(k.log_content.c_str());
printf("%d\n", t3-t2);
return 0;
}
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: 课堂作业-N皇后算法
Post Link: 课堂作业-N皇后算法