代码改变世界

一类棋盘互不攻击问题

2008-10-08 21:03  老博客哈  阅读(2855)  评论(11编辑  收藏  举报

一类棋盘互不攻击问题

                                 农夫三拳@seu(drizzlecrj@gmail.com)

     最近在SGU上做了一些棋盘上互不攻击的题目,稍稍的总结一下:

1. SGU 220 Little Bishops  以及 SGU 221 Big Bishops

问题:  求n*n的棋盘上放置k个互不攻击的象的个数。

解法:  将棋盘旋转45度之后,转换成二维动态规划求解。具体参见 黑书243~244页

转移的方程为 F(i,j) = F(i - 1, j) + F(i - 1, j - 1) * (Ri - j + 1)

其中F(i,j)表示前i行放置j个象的总数,Ri表示第i行的格子总数。那么显然F(i - 1, j)就是第i行不放任何象,F(i - 1, j - 1) * (Ri - j + 1)表示第i行放置1个象的情况。

 

2. SGU 222 Little Rooks

问题:  求n*n的棋盘上放置k个互不攻击的车的个数。

解法:  组合公式,挑选k个行C(n,k),挑选k个列的排列A(n,k),所以总数为C(n,k)*A(n,k)

 

3. SGU 223 Little Kings

问题:  求n*n的棋盘上放置k个互不攻击的王的个数。

解法:  状态压缩动态规划。dfs预处理两行之间的转移状态。

方程为:  F(i, j2, k) = Sigma{F(i - 1, j1, k - ONE(j2))}

F(i,j2,k)表示第i行状态为j,前i行放置k个王的总数, F(i - 1, j1, k - ONE(j2)) 为第i - 1行状态为j1(且j1和j2可以转移),前i - 1行放置 k - ONE(j2)个王的总数。

显然ONE(j2)为第i行放置的王的个数。

 

4.  SGU 224 Little Queens

问题:  求n*n的棋盘上放置k个互不攻击的后的个数。

解法: 参加我的这篇文章 《K皇后问题

 

5.  SGU 225 Little Knights

问题:  求n*n的棋盘上放置k个互不攻击的马的个数。

解法: 我的解法还做得不好,用的是和3中提到的相同的方法,不过时间复杂度太高了,貌似只能打表交。

我是用F(i,j2,j1,k)表示第i行状态为j2,第i-1行状态为j1,前i行放置k个马的总数,那么有

F(i,j2,j1,k) = Sigma{F(i-1,j1,j0,k - One(j2))} j0和j1能够转移到j2

不知道有没有更好的解法,希望过路大牛指教下。

 

小结:

对于在棋盘上放置棋子互不攻击的问题,如果问最值问题,例如:n*n的棋盘上最多能够放多少个互不攻击得象等等,问题通常可以转换为二分图模型来求解。

而对于更加通用的n*n棋盘上放置k个互不攻击的棋子的问题,我知道的做法有两种,一种是用容斥原理,另外一种就是状态压缩。其中后者更加通用一些。

欢迎指教!