n-queens的变化

时间:2014-05-18 21:00:43

标签: algorithm backtracking brute-force

您将获得NxM矩阵。你有K战舰。每个战舰还有3个参数 - rowAttack,columnAttack和diagonalAttack。每个都告诉船舶可以攻击的行/列/对角线(每个方向)中有多少个单元格。您的任务是找到船只是否可以放在船上,以便没有人互相攻击。

为了更好地了解这些攻击,比如说这艘船被放置在(5,5)并且它的列攻击范围是3,那么它可以从(5,2)到(5,8)攻击任何船只

如果没有这样的组合,则返回false。一个示例java类......

class BattleShip
{
     public final int rowAttack;
     public final int columnAttack;
     public final int diagonalAttack;
}

你需要编码

boolean isPossible(int m, int n, BattleShip battleShips[])

其中m是电路板中的行数,n是电路板中的列数,而battleShips.length为kk无关紧要同时mn。 (因此,一个明显的检查是检查k> = m x n)。

除了检查可能达到O(m x n x k!)的所有可能性之外,我想不出任何解决方案

2 个答案:

答案 0 :(得分:1)

这不是一个保证的多项式时间解决方案,但在实践中它可以比蛮力更快:对于棋盘上的每个方格和每个战舰索引,都有一个0/1整数变量,表明战列舰是否在广场。然后你可以有线性约束,说每个战列舰都放在板上一个地方,并且每艘战列舰都放在板上,对于给定的广场和战列舰,你不能在“射击距离”内拥有任何战列舰。任何方向的战舰这给出了O(mnk)变量中的O(mnk)约束,因此多项式问题描述的复杂性。然后,您可以将问题提供给0/1整数编程求解器,看看是否有解决方案。已经对0/1整数编程求解器进行了大量研究,并且已经对软件进行了大量优化,因此在实践中这可能比蛮力更快。顺便说一句,我不确定你是如何得到蛮力的引用...我对蛮力的限制要差得多,即O((mn)^ k)。

答案 1 :(得分:1)

说明中没有明确说明,但由于diagonalAttack参数与rowAttackcolumnAttack参数分开指定,因此似乎是一艘船"攻击区"形状像星号或星形,而不是实心矩形。在这种情况下,您将通过将船舶彼此偏移(2,1)(或(1,2))来获得非常紧密的包装:例如第一个在(0,0),另一个在(2,1),另一个在(4,2),依此类推。 (船舶之间的非零垂直和水平偏移分别保证没有船只可以被水平或垂直攻击击中;并且x和y偏移不同的事实保证了对角攻击区域也永远不会击中船只。)

到达电路板的(右侧或顶部)边缘后,您需要再次从(左侧或底部)边缘开始。现在事情变得稍微复杂一些,因为你必须注意不要让新船撞到或撞到它们下面的现有船只(在击中右边缘的情况下)。您可以像以前一样使用相同的x位置,但要将每艘船的位置向上调整到足以避免撞击或被其下方的任何船撞击;或者,你可以通过使用与之前相同的x位置但是将它们偏移1来获得更紧密的打包,以消除在垂直攻击区域中命中的可能性。

这只是一种启发式方法:如果它无法将所有船只装到纸板上,那么它并不一定意味着它们无法被打包。但它应该经常快速找到答案,如果你想开发一种使用回溯的精确方法(例如最佳优先搜索),那么我认为"运行这种启发式算法后成功放置的船只数量#34;将作为订购部分解决方案的有用方式。