回溯法求解N人分N本书的问题(Java实现)
2010-07-20 00:43
357 查看
分书问题与上一篇文章中的“回溯法求解N皇后问题(Java实现)”几乎是一样的,只不过在变成写代码求解时用到的数据结构比 N 皇后问题简单了许多,或许这个分书问题更能让人明白回溯法的使用情况。
分书问题:有编号为 A、B、C、D、E 的 5 本书,以及 5 个人,每本书可以分给每一个对该书有兴趣的人阅读,且每个人都只能分到一本自己感兴趣的书。问当给定 5 个人对 5 本书的感兴趣情况时,怎样分配这 5 本书才能让每个人都开始阅读。
思路:与 N 皇后问题几乎一致,每次都尝试给第 p 个人从 5 本书中分出他感兴趣的一本,若不能构成最终解,则撤销回溯到上一个人(即第 p – 1 个人)的分配。但是所需数据结构有所不同,我们如下确定:
int bookCounts 表示书的总数量,与总人数相等
int like [p] = 1 表示第 p 个人喜欢读第 b 本书,即具体的问题初始条件;
int given [b] = p 表示第 b 本书分给了第 p 个人,即保存解的标识数组;
注:[b]在这里 p ,b (即下标)都从 0 开始,这与上篇文章中的 N 皇后问题不同,N 皇后问题是为了数据处理更加直观些,而这里分数问题比较简单。
基于这种数据结构,算法实现如下:
对应于所给的问题规模,所得的解如下:
小结:
比较重要的还是根据问题选择、设计有利于解决问题、实现算法的数据结构。
分书问题:有编号为 A、B、C、D、E 的 5 本书,以及 5 个人,每本书可以分给每一个对该书有兴趣的人阅读,且每个人都只能分到一本自己感兴趣的书。问当给定 5 个人对 5 本书的感兴趣情况时,怎样分配这 5 本书才能让每个人都开始阅读。
思路:与 N 皇后问题几乎一致,每次都尝试给第 p 个人从 5 本书中分出他感兴趣的一本,若不能构成最终解,则撤销回溯到上一个人(即第 p – 1 个人)的分配。但是所需数据结构有所不同,我们如下确定:
int bookCounts 表示书的总数量,与总人数相等
int like [p] = 1 表示第 p 个人喜欢读第 b 本书,即具体的问题初始条件;
int given [b] = p 表示第 b 本书分给了第 p 个人,即保存解的标识数组;
注:[b]在这里 p ,b (即下标)都从 0 开始,这与上篇文章中的 N 皇后问题不同,N 皇后问题是为了数据处理更加直观些,而这里分数问题比较简单。
基于这种数据结构,算法实现如下:
/** * 回溯法求解分书问题 * @author haolloyin */ public class AllacateBooks { // 书的总数量,与总人数相等 private int bookCounts = 5; // like[p] 表示第 p 个人喜欢读第 b 本书 private int[][] like = new int[bookCounts][bookCounts]; // given[b] = p 表示将第 b 本书分配给第 p 个人 private int[] given = new int[bookCounts]; // 初始化标识数组 given[] 和传入各人喜欢书的情况数组 private void init(int like[][]) { for (int i = 0; i < bookCounts; i++) { given[i] = -1; // -1 表示第 i 本书还没分配出去 } this.like = like; } // 尝试给每一个人分配一本书 public void allocateBook(int person) { for (int bookNum = 0; bookNum < bookCounts; bookNum++) { if (like[person][bookNum] == 1 && given[bookNum] == -1) { given[bookNum] = person; if (person == bookCounts - 1) { // 打印结果 for (int i = 0; i < bookCounts; i++) { System.out.println("人 " + (given[i]+1) + " <---> 书 " + ((char)(i + 'A'))); } System.out.println(); } else { // 为下一个人分配一本书 allocateBook(person + 1); } // 失败,回溯重新寻找解 given[bookNum] = -1; } } } // 测试 public static void main(String[] args) { // 构造一个问题规模 int[][] like = new int[][]{ { 0, 0, 1, 1, 0 }, { 1, 1, 0, 0, 1 }, { 0, 1, 1, 0, 1 }, { 0, 0, 0, 1, 0 }, { 0, 1, 0, 0, 1 }}; AllacateBooks allocateBooks = new AllacateBooks(); allocateBooks.init(like); allocateBooks.allocateBook(0); } }
对应于所给的问题规模,所得的解如下:
[b]人 2 <---> 书 A 人 3 <---> 书 B 人 1 <---> 书 C 人 4 <---> 书 D 人 5 <---> 书 E 人 2 <---> 书 A 人 5 <---> 书 B 人 1 <---> 书 C 人 4 <---> 书 D 人 3 <---> 书 E
小结:
比较重要的还是根据问题选择、设计有利于解决问题、实现算法的数据结构。
相关文章推荐
- 贪心法和回溯法 求解“背包、0/1背包问题”——Java 实现
- 回溯法求解 “n 皇后 问题”——Java 实现
- 回溯法求解N皇后问题(Java实现)
- 算法java实现--回溯法--图的m着色问题
- Josephus环问题求解(Java实现)
- 算法java实现--回溯法--最大团问题
- 用Java实现天平称球问题的自动求解
- 算法java实现--回溯法--电路板排线问题--排列树
- 蚁群算法java实现以及TSP问题蚁群算法求解
- 算法java实现--回溯法--装载问题
- 蚁群算法java实现以及TSP问题蚁群算法求解
- 0/1背包问题的动态规划法求解 —— Java 实现
- 同 用Java实现天平称球问题的自动求解
- 动态规划求解背包问题(JAVA实现)
- 0/1背包问题的动态规划法求解 —— Java 实现
- 0/1背包问题的动态规划法求解 —— Java 实现
- Java实现的求解经典罗马数字和阿拉伯数字相互转换问题示例
- 动态规划求解矩阵连乘问题Java实现
- 蚁群算法的Java实现求解TSP问题
- 回溯法解决N皇后问题(java实现)