精華區beta C_and_CPP 關於我們 聯絡資訊
作者 bleed1979 (十三) 看板 C_and_CPP 標題 [ACM ] 10154 烏龜塔 解法 時間 Wed Apr 21 13:50:54 2010 2010.04.23 09:40 修訂二版 http://nopaste.csie.org/d3f4a 方法和一版是一樣的,可是跑出來結果卻不相同。 Bleed ====================================================================== 2010.04.23 00:14 修訂一版 修訂一版程式碼︰http://nopaste.csie.org/c4691 1.僅將負載重量由小到大排序。 2.LIS精神 + 額外的替換烏龜。 配置一維累積重量陣列acc_weight,初始為0。 配置二維的烏龜重量序列, 一開始都是空的。 (這裡放得是烏龜的重量,不是第幾隻烏龜。) 配置一維烏龜重量序列中序列一定會有的烏龜重量的index。 (代表第i個序列,一定會有第i隻烏龜的重量,因為他至少會負載自己, 要把該index記起來,以防替代的時候不小心替代錯誤。) 2.1 跑一次for迴圈對i序列放入烏龜i的重量, 並且acc_weight[i] = weight[i], 一定會有的烏龜重量index為0。 2.2 for ( 第i烏龜(i從第一隻開始)到最後一隻烏龜 ) { // 第一階段,判斷多一隻的情況 for( j = 第i隻烏龜到最後一隻烏龜) { if (acc_weight[i] + 烏龜j重量 <= 烏龜j能負載的重量 並且 烏龜重量序列[i]的隻數 + 1 >= 烏龜重量序列[j]的隻數) { if (烏龜重量序列[i]的隻數 + 1 > 烏龜重量序列[j]的隻數) { 烏龜重量序列[j] = 烏龜重量序列[i] 再將烏龜j重量放入烏龜重量序列[j] acc_weight[j] = acc_weight[i] + 烏龜j的重量 index要對應烏龜j } else // 隻數i + 1 和隻數j 相等 { if (acc_weight[j] == 0 或者 acc_weight[j] > acc_weight[i] + 烏龜j重量) { 烏龜重量序列[j] = 烏龜重量序列[i] 再將烏龜j重量放入烏龜重量序列[j] acc_weight[j] = acc_weight[i] + 烏龜j的重量 index要對應烏龜j } } } } else // 第二判斷,做替換烏龜的動作。 { 如果烏龜i放進序列j裡面可以減輕序列j的累積重量, 並且根據index判斷替換的烏龜並不是烏龜j(序列j裡面烏龜j一定要存在), 將烏龜i放入序列j裡, 並拿掉最重的烏龜或次重的烏龜(烏龜j是最重的那就跟次重的比)。 這段的實做請參閱程式碼。寫得並不太漂亮。 } } 原文程式的盲點在於,我忽略了序列j裡面烏龜j一定要存在。 所以之前替換掉了烏龜j且並未做判斷。 雖然AC,但是只是運氣好罷了。 目前這個程式可以AC也測試過了版上的測資。如果還有更critical的測資,我再做修訂。 Bleed ============================================================================== 將[一個感覺是 dynamic programming 的題目]做一個結論。 D網友說得Prob_Solve的l網友用的是LIS,其實算是對的。 l網友判斷依據在於LIS的第二個內for迴圈,以下將有程式架構和原因及程式碼。 l網友的方法也是對的,因為在LIS的迭代過程中, 這方法就是將累積重量降到最低以方便後面的烏龜承受重量。 (這裡說得對的,至少是能通過UVa的judge。不曉得有沒有更critical的測資。) 程式架構︰ 1.將負載重量由小到大排序,當然重量要對應好。 2.LIS 配置累積重量陣列acc_weight。 配置二維的烏龜重量序列, 一開始都是空的。 (這裡放得是烏龜的重量,不是第幾隻烏龜。) for ( 第i烏龜(i從第一隻開始)到最後一隻烏龜 ) { if (acc_weight[i] == 0) { acc_weight[i] = 第i隻烏龜的重量 將第i隻烏龜的重量放入烏龜重量序列[i] } // 第一階段,判斷多一隻的情況 for( j = 第i隻烏龜到最後一隻烏龜) { if (acc_weight[i] + 烏龜j重量 <= 烏龜j能負載的重量 並且 烏龜重量序列[i]的隻數 + 1 >= 烏龜重量序列[j]的隻數) { if (烏龜重量序列[i]的隻數 + 1 > 烏龜重量序列[j]的隻數) { 烏龜重量序列[j] = 烏龜重量序列[i] 再將烏龜j重量放入烏龜重量序列[j] acc_weight[j] = acc_weight[i] + 烏龜j的重量 } else // 隻數i + 1 和隻數j 相等 { if (acc_weight[j] == 0 或者 acc_weight[j] > acc_weight[i] + 烏龜j重量) { 烏龜重量序列[j] = 烏龜重量序列[i] 再將烏龜j重量放入烏龜重量序列[j] acc_weight[j] = acc_weight[i] + 烏龜j的重量 } } } } // 第二階段,將累積重量降到最低,同l網友的方法 for( j = 第i隻烏龜到最後一隻烏龜) { if (烏龜重量序列[i]的隻數 == 烏龜重量序列[j]的隻數 並且 烏龜重量序列[i]裡最重的比烏龜j重量還要重) { 烏龜重量序列[j] = (烏龜重量序列[i] 扣掉 最重的烏龜) 再將烏龜j重量放入烏龜重量序列[j] acc_weight[j] = acc_weight[i] - 最重的烏龜 + 烏龜j的重量 } } } 這裡就是測試通過的實做程式碼: http://nopaste.csie.org/c785a 為什麼要多做第二階段? 因為如果序列長度一樣,但累積重量可以比較小, 當然是換成累積重量比較小的序列,以方便之後的烏龜負載。 為什麼要和最重的比? 因為拿掉最重的相當於此序列瘦身最大的程度。減輕最多的意思。 Bleed -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.32.177.97
scars:我來看熱鬧的 04/22 05:34
walker2009:嗚嗚,我已經習慣看英文變數了,中文變數看到頭昏(遮臉) 04/22 11:53
※ 編輯: bleed1979 來自: 114.32.177.97 (04/23 00:15) ※ 編輯: bleed1979 來自: 114.32.177.97 (04/23 00:29) ※ 編輯: bleed1979 來自: 114.32.177.97 (04/23 09:41)