Algorithm 广度优先搜索:骑士封面
我正在努力学习USACO的算法培训课程()——目前我正在一个页面上介绍DFS、BFS等。我确实理解这些概念,但他们为BFS提供的示例问题——骑士封面——让我感到困惑。以下是问题陈述: 在n x n棋盘上放置尽可能少的骑士,这样每个方块都会受到攻击。骑士不被认为可以攻击它所在的广场 这是BFS,页面上说,因为它在尝试Algorithm 广度优先搜索:骑士封面,algorithm,breadth-first-search,Algorithm,Breadth First Search,我正在努力学习USACO的算法培训课程()——目前我正在一个页面上介绍DFS、BFS等。我确实理解这些概念,但他们为BFS提供的示例问题——骑士封面——让我感到困惑。以下是问题陈述: 在n x n棋盘上放置尽可能少的骑士,这样每个方块都会受到攻击。骑士不被认为可以攻击它所在的广场 这是BFS,页面上说,因为它在尝试n+1knights之前,尝试看看是否有一个解决方案,这是非常清楚的 然而,我不明白如何仅从这一点来制定解决方案。有人能帮我找到这个的伪代码吗 非常感谢 它是BFS,但你不搜索棋盘;搜
n+1
knights之前,尝试看看是否有一个解决方案,这是非常清楚的
然而,我不明白如何仅从这一点来制定解决方案。有人能帮我找到这个的伪代码吗
非常感谢 它是BFS,但你不搜索棋盘;搜索放置空间: 初始状态:没有放置骑士 有效移动:在任何未占用的地砖上放置一名骑士 目标状态:所有瓦片要么被占领,要么被攻击 基本算法(状态空间的BFS):
- 将初始状态推送到BFS队列
- 当队列中有东西时:
- 从队列中删除一个状态
- 对于每个未占用的瓷砖:
- 创建当前状态的副本
- 将一名骑士添加到该平铺中
- 如果队列中不存在新状态:
- 如果新状态是目标状态,请完成
- 否则将其添加到队列中
你可以要求骑士从左到右,从上到下。这样就不需要检查队列中是否有重复项。此外,如果您知道在不违反插入顺序的情况下无法攻击未锁定的磁贴,则可以提前放弃状态 如果不这样做,同时保留重复检查,算法仍将生成正确的结果,但速度会慢得多。慢40000倍,大约(8!=40320是8骑士状态的重复数)
如果您想要更快的算法,请查看*。这里,一个可能的启发是:
- 计算未固定和未占用的瓷砖数量
- 将计数除以九,四舍五入(一个骑士不能攻击超过八个新牌或占据超过一个)
- 距离(需要增加的骑士数量)不超过这个数字
技术细节: 您可以将每个状态表示为64位掩码。虽然这需要一些位操作,但它确实有助于内存,而且64位数字的相等性检查速度很快。如果您没有64位数字,请使用两个32位数字-这些数字应该可用
循环数组队列是高效的,扩展其容量并不困难。如果您必须实现自己的队列,请选择此队列 > P>这是C++中的一个实现。 它只使用基本的蛮力,因此只有在
n=5
之前才有效
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
bool isFinal(vector<vector<bool> >& board, int n)
{
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(!board[i][j])
return false;
}
}
return true;
}
void printBoard(vector<pair<int,int> > vec, int n)
{
vector<string> printIt(n);
for(int i = 0; i < n; ++i)
{
string s = "";
for(int j = 0; j < n; ++j)
{
s += ".";
}
printIt[i] = s;
}
int m = vec.size();
for(int i = 0; i < m; ++i)
{
printIt[vec[i].first][vec[i].second] = 'x';
}
for(int i = 0; i < n; ++i)
{
cout << printIt[i] << endl;
}
cout << endl;
}
void updateBoard(vector<vector<bool> >& board, int i, int j, int n)
{
board[i][j] = true;
if(i-2 >= 0 && j+1 < n)
board[i-2][j+1] = true;
if(i-1 >= 0 && j+2 < n)
board[i-1][j+2] = true;
if(i+1 < n && j+2 < n)
board[i+1][j+2] = true;
if(i+2 < n && j+1 < n)
board[i+2][j+1] = true;
if(i-2 >= 0 && j-1 >= 0)
board[i-2][j-1] = true;
if(i-1 >= 0 && j-2 >= 0)
board[i-1][j-2] = true;
if(i+1 < n && j-2 >= 0)
board[i+1][j-2] = true;
if(i+2 < n && j-1 >= 0)
board[i+2][j-1] = true;
}
bool isThere(vector<pair<int,int> >& vec, vector<vector<pair<int,int> > >& setOfBoards, int len)
{
for(int i = 0; i < len; ++i)
{
if(setOfBoards[i] == vec)
return true;
}
return false;
}
int main()
{
int n;
cin >> n;
vector<vector<pair<int,int> > > setOfBoards;
int len = 0;
vector<vector<bool> > startingBoard(n);
for(int i = 0; i < n; ++i)
{
vector<bool> vec(n,0);
startingBoard[i] = vec;
}
vector<pair<int,int> > startingVec;
vector<vector<vector<vector<bool> > > > q1;
vector<vector<vector<pair<int,int> > > > q2;
vector<vector<vector<bool> > > sLayer1;
vector<vector<pair<int,int> > > sLayer2;
sLayer1.push_back(startingBoard);
sLayer2.push_back(startingVec);
q1.push_back(sLayer1);
q2.push_back(sLayer2);
int k = 0;
bool flag = false;
int count = 0;
while(!flag && !q1[k].empty())
{
int m = q1[k].size();
vector<vector<vector<bool> > > layer1;
vector<vector<pair<int,int> > > layer2;
q1.push_back(layer1);
q2.push_back(layer2);
for(int l = 0; l < m; ++l)
{
vector<vector<bool> > board = q1[k][l];
vector<pair<int,int> > vec = q2[k][l];
if(isFinal(board, n))
{
while(l < m)
{
board = q1[k][l];
vec = q2[k][l];
if(isFinal(board, n))
{
printBoard(vec, n);
++count;
}
++l;
}
flag = true;
break;
}
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(!board[i][j])
{
pair<int,int> p;
p.first = i;
p.second = j;
vector<vector<bool> > newBoard = board;
vector<pair<int,int> > newVec = vec;
newVec.push_back(p);
updateBoard(newBoard, i, j, n);
sort(newVec.begin(), newVec.end());
if(!isThere(newVec, setOfBoards, len))
{
q1[k+1].push_back(newBoard);
q2[k+1].push_back(newVec);
setOfBoards.push_back(newVec);
++len;
}
}
}
}
}
++k;
}
cout << count << endl;
}
#包括
#包括
#包括
使用名称空间std;
bool isFinal(矢量和板,整数n)
{
对于(int i=0;i=0)
董事会[i-2][j-1]=正确;
如果(i-1>=0&&j-2>=0)
董事会[i-1][j-2]=正确;
如果(i+1=0)
董事会[i+1][j-2]=正确;
如果(i+2=0)
董事会[i+2][j-1]=正确;
}
布尔值在此(向量和向量,向量和板组,整数)
{
对于(int i=0;i>n;
向量板组;
int len=0;
矢量右舷(n);
对于(int i=0;i