1.貪心算法介紹?
1.算法思路
貪心算法的基本思路是從問題的某一個初始解出發一步一步地進行,根據某個優化測度,每一 步都要確保能獲得局部最優解。每一步只考慮一 個數據,其選取應該滿足局部優化的條件。若下 一個數據和部分最優解連在一起不再是可行解時, 就不把該數據添加到部分解中,直到把所有數據枚舉完,或者不能再添加算法停止。?
貪心算法一般按如下步驟進行:?
①建立數學模型來描述問題?。
②把求解的問題分成若干個子問題?。
③對每個子問題求解,得到子問題的局部最優解?。
④把子問題的解局部最優解合成原來解問題的一個解?。
貪心算法是一種對某些求最優解問題的更簡單、更迅速的設計技術。貪心算法的特點是一步一步地進行,常以當前情況為基礎根據某個優化測度作最優選擇,而不考慮各種可能的整體情況,省去了為找最優解要窮盡所有可能而必須耗費的大量時間。貪心算法采用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇,就將所求問題簡化為一個規模更小的子問題,通過每一步貪心選擇,可得到問題的一個最優解。雖然每一步上都要保證能獲得局部最優解,但由此產生的全局解有時不一定是最優的,所以貪心算法不要回溯?。
2.代碼介紹
private static void assignTeachersToProjects(TeacherDao teacherDao, ResearchProjectDao projectDao) {// 從TeacherDao獲取所有教師的列表List<Teacher> teachers = teacherDao.getAllTeachers();// 從ResearchProjectDao獲取所有科研項目的列表List<ResearchProject> projects = projectDao.getAllResearchProjects();// 使用職務ID和職稱ID對教師進行排序,職務和職稱越高的教師排在前面// 這里reversed()表示降序排序Collections.sort(teachers, Comparator.comparing(Teacher::getPositionID).reversed().thenComparing(Teacher::getTitleID).reversed());// 使用預算和開始時間對項目進行排序,預算越高和開始時間越早的項目排在前面// 預算高的排在前面,如果預算相同,則開始時間早的排在前面Collections.sort(projects, Comparator.comparing(ResearchProject::getBudget).reversed().thenComparing(ResearchProject::getStartDate));// 創建一個映射,用于記錄教師與項目之間的分配關系Map<Integer, Integer> teacherToProjectMap = new HashMap<>();try {// 遍歷每個項目for (ResearchProject project : projects) {// 使用Stream API尋找尚未分配項目的教師// filter條件確保只考慮那些還沒有分配項目的教師Teacher bestTeacher = teachers.stream().filter(teacher -> !teacherToProjectMap.containsKey(teacher.getTeacherID())).findFirst().orElse(null);// 如果找到了合適的教師if (bestTeacher != null) {// 將教師ID設置為項目的負責人IDproject.setTeacherInChargeID(bestTeacher.getTeacherID());// 將教師ID和項目ID添加到映射中,表示教師已被分配項目teacherToProjectMap.put(bestTeacher.getTeacherID(), project.getProjectID());// 打印推薦信息System.out.println("推薦項目 '" + project.getTitle() + "' 分配給教師 " + bestTeacher.getName());// 調用ResearchProjectDao的updateResearchProject方法更新數據庫中的項目分配信息projectDao.updateResearchProject(project);} else {// 如果沒有找到合適的教師,打印無法推薦的消息System.out.println("未找到未分配的教師,無法推薦項目 '" + project.getTitle() + "'");}}} catch (Exception e) {// 如果發生異常,打印錯誤信息并打印堆棧跟蹤System.out.println("更新數據庫時發生錯誤:" + e.getMessage());e.printStackTrace();}// 打印教師和項目的總數信息System.out.println("教師總數:" + teachers.size());System.out.println("項目總數:" + projects.size());}
3.使用貪心算法為教師分配較為合適的科研項目
這段代碼實現了一個教師與科研項目分配的功能,其核心算法思想是貪心算法。以下是代碼中使用的算法分析:
1. 貪心算法:在為每個科研項目選擇負責人時,算法嘗試為每個項目找到一個尚未分配項目的教師。這是貪心算法的一個典型應用,因為它在每一步都做出局部最優的選擇(即選擇當前可用的最佳教師),希望這樣的局部最優決策能夠導致全局的最優或近似最優解。
2. 排序:代碼首先對教師和項目進行排序。
? ?教師根據職務ID和職稱ID降序排序,意味著職務和職稱較高的教師會被排在前面。
? ?項目根據預算降序排序,預算越高的項目越先被考慮;如果預算相同,則根據開始時間升序排序,即開始時間越早的項目越先被考慮。
3. 過濾和選擇:使用Java 8的Stream API,通過過濾條件`.filter(teacher -> !teacherToProjectMap.containsKey(teacher.getTeacherID()))`選擇尚未分配項目的教師。這是選擇算法的一部分,確保每個教師只被分配一個項目。
4. 映射關系:使用`teacherToProjectMap`來記錄已經分配項目的教師,有助于避免重復分配。
5. 異常處理:使用`try-catch`結構來處理可能發生的異常,確保程序的健壯性。
6. 數據庫操作:在`try`塊中,通過調用`projectDao.updateResearchProject(project)`方法將分配結果更新到數據庫。這是實現功能的最后一步,將推薦結果持久化。
4.概括
在這段代碼中,雖然沒有明確提到“貪心算法”這個術語,但實際上代碼的邏輯體現了貪心算法的思想。貪心算法是一種在每一步選擇中都采取在當前狀態下最好或最優(即最有利)的選擇,從而希望導致結果是全局最好或最優的算法。
具體來說,代碼中的貪心策略體現在以下幾個方面:
-
教師分配策略:在分配教師到項目時,代碼總是選擇當前未分配項目的教師中職務和職稱最高的教師(即排序后的第一個教師)。這是一種局部最優選擇,希望以此來達到全局最優(即盡可能讓職務和職稱高的教師負責項目)。
-
項目分配策略:在分配項目時,代碼總是選擇預算最高且開始時間最早的項目。這也是一種局部最優選擇,希望以此來達到全局最優(即盡可能讓預算高且開始時間早的項目得到優先分配)。
這段代碼通過在每一步選擇中都采取當前狀態下最優的選擇(即職務和職稱最高的教師、預算最高且開始時間最早的項目),體現了貪心算法的思想。