已知乙個 n 枚郵票的面值集合(如,)和乙個上限 k —— 表示信封上能夠貼 k 張郵票。計算從 1 到 m 的最大連續可貼出的郵資。
例如,假設有 1 分和 3 分的郵票;你最多可以貼 5 張郵票。很容易貼出 1 到 5 分的郵資(用 1 分郵票貼就行了),接下來的郵資也不難:
6 = 3 + 3
7 = 3 + 3 + 1
8 = 3 + 3 + 1 + 1
9 = 3 + 3 + 3
10 = 3 + 3 + 3 + 1
11 = 3 + 3 + 3 + 1 + 1
12 = 3 + 3 + 3 + 3
13 = 3 + 3 + 3 + 3 + 1
然而,使用 5 枚 1 分或者 3 分的郵票根本不可能貼出 14 分的郵資。因此,對於這兩種郵票的集合和上限 k=5,答案是 m=13。
我們先給出將其看為多重集組合數來解得場景,不同之處在於,這裡限制了郵票使用的最大數目。我們使用兩個陣列
d p[
i],c
nt[i
]dp[i],cnt[i]
dp[i],
cnt[
i]表示使用最少cnt
[i
]cnt[i]
cnt[i]
個郵票就能拼湊出大小為i
ii的郵資,那麼動態規劃的過程分為三步
for
(int i =
1; i <= n; i++
)cin >> a[i]
;sort
(a +
1, a + n)
; dp[0]
=1; ll sum = k * a[n]
, maxj =0;
//最多能湊成的郵資
for(
int i =
1; i <= n; i++
)else dp[j + k * a[i]]=
1, cnt[j + k * a[i]
]= cnt[j]
+ k;}}
maxj = k * a[i]
;}
不幸的是,多重集組合數經常面臨著tle的危險,上面也不例外,只能拿80分,看了大佬的題解之後發現自己是乙個zz,其實只需要很簡單得轉換,我們就能拿下這道題,
注意看題,題目求得是從1開始得最長連續序列,因此我們只需要從i=0不斷向上搜尋,直到有乙個i不能拼湊出來,就得到了最長連續序列
最重要的部分只有4行,dp[
i]
dp[i]
dp[i
]是我們拼湊出i
ii郵資使用的最少郵票數目,dp得過程其實就是不斷更新最小郵票數目得過程,在滿足數目要求dp[
i]
<=k
dp[i]<=k
dp[i
]<=k
時,我們先將dp[
i+1]
dp[i+1]
dp[i+1
]設定為inf,然後遍歷每一種郵票,確保郵票得價值小於當前得i
ii(注意這裡要保證a從小到大排列),然後再滿足上述條件得情況下,使得dp[
i]
dp[i]
dp[i
]總是最小得
while
(dp[i]
<= k)
#define ll int
#define inf 0x3f3f3f3f
#define max 55
#define vec vector
#define p pair
//dp[j]:湊出j需要的最小郵票數目
int k, n, a[max]
, dp[
2000005];
intmain()
cout << i -
1<< endl;
}}
有趣的DP 郵票問題
題目描述 給定乙個信封,最多隻允許貼上n n 100 張郵票,我們現在有m m 100 種郵票,面值分別為 x1,x2 xm xi 255為正整數 並假設各種郵票都有足夠多張。要求計算所能獲得的郵資最大範圍。即求最大值max,使1 max之間的每乙個郵資都能得到。例如 n 4,有2種郵票,面值分別為...
簡單環(狀壓 dp,詳細注釋)
參考部落格 牛客網 wannafly挑戰賽17 c 簡單環 狀壓dp 題目描述 給定一張n個點m條邊的無向圖,求出圖中所有簡單環的數量。簡單環 簡單環又稱簡單迴路,圖的頂點序列中,除了第乙個頂點和最後乙個頂點相同外,其餘頂點不重複出現的迴路叫簡單迴路。或者說,若通路或迴路不重複地包含相同的邊,則它是...
DP 經典問題解析
解決dp 動態規劃 問題是需要思維訓練的,下面列舉了四個經典的dp問題和解析,希望對大家有幫助。題目比較長,在此略去了,可以從網上搜到具體描述。一 最長單調遞增子串行問題 遞減同理 1 用乙個陣列b n 記錄以a i 結尾的最長單調遞增子串行的長度 2 b i max 1,b 0 1 3 序列a的最...