博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
回溯法求解N人分N本书的问题(Java实现)
阅读量:6340 次
发布时间:2019-06-22

本文共 1991 字,大约阅读时间需要 6 分钟。

分书问题与上一篇文章中的“”几乎是一样的,只不过在变成写代码求解时用到的数据结构比 N 皇后问题简单了许多,或许这个分书问题更能让人明白回溯法的使用情况。

分书问题:有编号为 A、B、C、D、E 的 5 本书,以及 5 个人,每本书可以分给每一个对该书有兴趣的人阅读,且每个人都只能分到一本自己感兴趣的书。问当给定 5 个人对 5 本书的感兴趣情况时,怎样分配这 5 本书才能让每个人都开始阅读。

思路:与 N 皇后问题几乎一致,每次都尝试给第 p 个人从 5 本书中分出他感兴趣的一本,若不能构成最终解,则撤销回溯到上一个人(即第 p – 1 个人)的分配。但是所需数据结构有所不同,我们如下确定:

int bookCounts 表示书的总数量,与总人数相等

int like [p] [b] = 1 表示第 p 个人喜欢读第 b 本书,即具体的问题初始条件;

int given [b] = p 表示第 b 本书分给了第 p 个人,即保存解的标识数组;

注:在这里 p ,b (即下标)都从 0 开始,这与上篇文章中的 N 皇后问题不同,N 皇后问题是为了数据处理更加直观些,而这里分数问题比较简单。

基于这种数据结构,算法实现如下:

 
  1. /**  
  2.  * 回溯法求解分书问题  
  3.  * @author haolloyin  
  4.  */ 
  5. public class AllacateBooks {  
  6.  
  7.     // 书的总数量,与总人数相等  
  8.     private int bookCounts = 5;  
  9.  
  10.     // like[p][b] 表示第 p 个人喜欢读第 b 本书  
  11.     private int[][] like = new int[bookCounts][bookCounts];  
  12.  
  13.     // given[b] = p 表示将第 b 本书分配给第 p 个人  
  14.     private int[] given = new int[bookCounts];  
  15.  
  16.     // 初始化标识数组 given[] 和传入各人喜欢书的情况数组  
  17.     private void init(int like[][]) {  
  18.         for (int i = 0; i < bookCounts; i++) {  
  19.             given[i] = -1// -1 表示第 i 本书还没分配出去  
  20.         }  
  21.         this.like = like;  
  22.     }  
  23.  
  24.     // 尝试给每一个人分配一本书  
  25.     public void allocateBook(int person) {  
  26.         for (int bookNum = 0; bookNum < bookCounts; bookNum++) {  
  27.  
  28.             if (like[person][bookNum] == 1 && given[bookNum] == -1) {  
  29.                 given[bookNum] = person;  
  30.  
  31.                 if (person == bookCounts - 1) {  
  32.                     // 打印结果  
  33.                     for (int i = 0; i < bookCounts; i++) {  
  34.                         System.out.println("人 " + (given[i]+1) + " <---> 书 " 
  35.                                 + ((char)(i + 'A')));  
  36.                     }  
  37.                     System.out.println();  
  38.                 } else {  
  39.                     // 为下一个人分配一本书  
  40.                     allocateBook(person + 1);  
  41.                 }  
  42.                 // 失败,回溯重新寻找解  
  43.                 given[bookNum] = -1;  
  44.             }  
  45.         }  
  46.     }  
  47.  
  48.     // 测试  
  49.     public static void main(String[] args) {  
  50.         // 构造一个问题规模  
  51.         int[][] like = new int[][]{   
  52.                 { 00110 },   
  53.                 { 11001 },  
  54.                 { 01101 },  
  55.                 { 00010 },   
  56.                 { 01001 }};  
  57.  
  58.         AllacateBooks allocateBooks = new AllacateBooks();  
  59.         allocateBooks.init(like);  
  60.         allocateBooks.allocateBook(0);  
  61.     }  


对应于所给的问题规模,所得的解如下:

人 2 <---> 书 A人 3 <---> 书 B人 1 <---> 书 C人 4 <---> 书 D人 5 <---> 书 E人 2 <---> 书 A人 5 <---> 书 B人 1 <---> 书 C人 4 <---> 书 D人 3 <---> 书 E


小结:

比较重要的还是根据问题选择、设计有利于解决问题、实现算法的数据结构。

本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/353200,如需转载请自行联系原作者

你可能感兴趣的文章
SVG的text使用
查看>>
Mybatis深入之事务管理
查看>>
Google Java编程库Guava介绍
查看>>
html ul li的学习
查看>>
Android 带password输入界面的Dialog实现机制
查看>>
一致性hash算法简介
查看>>
制作U盘启动盘及安装操作系统的方法
查看>>
EXT4.2--Ext Designer 使用
查看>>
Codeforces Round #343 (Div. 2) B. Far Relative’s Problem 暴力
查看>>
【HDU 4602】Partition
查看>>
windows7下virtualBox配置识别usb
查看>>
如何判断一个对象是否是数组。
查看>>
CF Zepto Code Rush 2014 B. Om Nom and Spiders
查看>>
Sublime Text 3103 Crack 破解 注册码
查看>>
html 表格
查看>>
(笔记)Linux内核学习(九)之内核内存管理方式
查看>>
HTTP ----通信机制
查看>>
Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引
查看>>
EF Code First Migrations数据库迁移
查看>>
I.MX6 Android backlight modify by C demo
查看>>