POJ1010 體現搜尋藝術的「水」題

2022-07-27 02:33:17 字數 1440 閱讀 5980

問題簡述

給出不同型別的一組郵票,型別面值可能相同。求符合總面值,且最多取4張郵票的最佳方案。最佳方案滿足以下要求:

型別數最多。

如果型別數相同,則張數少者。

如果張數也相同,則單張面值最大者。

如果以上都相同,則無最佳方案(平局)。

問題分析

搞了整整3天,絞盡腦汁也沒想出個好方案。看了一下關於該題的discussion,許多人說這是個水題,直接暴搜就可以過。可是怎麼都想不明白如何暴搜。 最後在網上看到乙個利用動態規劃法寫的乙個狀態轉移方程,頓時豁然開朗,想出了這個方案。關鍵在於如何遞迴計算最大型別數,以及判斷最優解。

一. 計算最大型別數

用mt[k][n][v] (k>=0, 0<=n<=4, v>=0) 表示從前k個型別中,最多取n張,總面值為v的所有組合中最大的型別數。則有遞推方程:

mt[k][n][v] = max  (0<=i<=n, v>=i*values[k-1])

二. 判斷最優解,平局,及無解情況  

<1>每次進行遞迴之前,先記錄當前型別取用的個數 

<2>每次遞迴到v=0時,即得到乙個解,與之前的最優解比較,決定是否更新或平局。 

<3>每次遞迴到n=0或v=0時, 如果v>0, 則此次遞迴無解。

基本**也很簡潔:

void searchbestcomb(int k, int n, int v)

else if(v==0)

updatebestcomb(k); //find an answer

}

提交後一次ac。看了一下acm的解題報告,終於知道如何暴搜了,雖然效率不高,但也可以過。**如下:

for(i=1;i<=total_stamps;i++)

for(j=i;j<=total_stamps;j++)

for(k=j;k<=total_stamps;k++)

for(l=k;l<=total_stamps;l++)

關鍵還是我沒利用好最多只有4張郵票這個條件,終於知道為什麼那麼多人說這是個水題了。在被此題困擾的時候我忘了乙個基本原則:人類有尋求最簡的天性。

反思:acm的題確實有趣,但確實很有挑戰。一道題對於經過專業訓練的人來說也許是小菜一碟,但對我們這些沒受過訓練,演算法水品一般般,僅憑興趣研究的人來說可能是一場頭腦風暴。苦思冥想幾天可能還想不出乙個解決方案,即使好不容易憋出乙個方案,也可能由於太繁瑣而無法實現,或者勉強實現了也錯誤百出。acmer不僅僅在基本演算法運用方面靈活自如,比如貪心,回溯,動態規劃等等,更重要的是,他們更善於用數學符號清晰地表達他們解題思路,比如用乙個遞推方程,方程寫出來後,**邏輯就清晰多了。我們普通演算法愛好者的差距就在這裡。這幾天有點過分投入了,腦力消耗很大,現在需要心平氣和,認清自己的現實情況。也許需要去啃一部《演算法導論》之類的名著來打牢基礎。無論如何,我會堅持下去。

POJ1010 搜尋題基礎

雖然也認同這題是基礎的搜尋題,但因做題太不熟練,寫了好久 include include include using namespace std const int n 4 const int nn 1000 int n,types,sum,maxz,a nn hash nn p n s n boo...

HDU 1010 深度搜尋問題

杭電acm 1010 題意 能否在 恰好t步時 從s點到達 d點,每個點只能走一次,x是障礙。注意不能提前到達,必須在t步時到達 我用的深度搜尋dfs,最重要的是超時問題。這裡涉及到乙個剪枝,我在網上看到的奇偶剪枝。m n的 0,1 矩陣 0,1,0,1,0 1,0,1,0,1 0,1,0,1,0 ...

poj 折半搜尋

題意 給你乙個含有n n 1000 個數的數列,問這個數列中是否存在四個不同的數a,b,c,d,使a b c d 若存在則輸出最大的d 思路 完全暴力的話o n 4 會t,可以考慮雙向搜尋,公式變形為a b d c 分別列舉a b和c d,將值和下標存在結構體中,再二分查詢即可 include in...