題目大意
大致題意:
給出幾類珍珠,以及它們的單價,要求用最少的錢就可以買到相同數量的,相同(或更高)質量的珍珠。
【規定買任一類的珍珠n個(價格爲p),都要支付(n+10)p的錢,即額外支付10p】
樣例分析
例如樣例Input的第二個例子:
3
1 10
1 11
100 12
需要買第一類1個,第二類1個,第三類100個
按常規支付爲 (1+10)*10 + (1+10)*11 + (100+10)*12 = 1551元(一共買了102個珍珠)
但是如果全部都按照第三類珍珠的價格支付,同樣是買102個,而且其中總體質量還被提高了,但是價格卻下降了:(102+10)*12 = 1344元
而對於樣例Input的第一個例子:
2
100 1
100 2
按常規支付爲 (100+10)*1 + (100+10)*2 =330元
但是全部按第二類珍珠的價格支付,同樣買200個,雖然總體質量提升了,但是價格也提高了: (202+10)*2=424元
貪心爲什麼錯
一開始想過從頭到尾遍歷珍珠的價格和數目,每次都看相臨的兩個,如果把當前這一批放入下一個等級價格降低,則將他放到下一個等級,否則直接算在當前等級的買的價格加到答案中,最後一等後設置最大值,保證不會再向後放.,但是這樣的思路其實是錯誤的,以下是證明:
價格
假設貪心得出和兩個前提
但是對於即不採取歸併更小的情況是否存在呢
化簡式子:
對比條件,我們知道
完全可以有
所以貪心策略是錯的
爲什麼可以dp以及dp的證明
首先證明最優解中肯定不會有交叉的替換,即在質量爲a<b<j<c<d的情況下,如果a被c替換,那麼b也一定要被c替換 假設在最優解中存在:a被c替換且b不被c替換的情況:
1.b不被任何替換 那麼此時把a換成用b替換 得到比原來更優的解,錯誤
2.b被j替換,此時把a換成用j替換 得到比原來更優的解,錯誤
3.b被d替換,此時把b換成用c替換 得到比原來更優的解,錯誤
因此,不存在交叉的替換,那麼最優解分爲下面兩種情況:
1.不存在斷點,即所有的都用最大一種替換,
2.存在斷點,最後一個斷點爲i,那麼最優解必爲
每個點都有可能是最後一個斷點,因此產生了我們的DP方程:
把dp[0]設成0的話 2就包含了1 dp[c]就是最後的答案
有點像最長上升子序列的問題
int T, N, a[MAX], p[MAX], dp[MAX];
int main() {
cin >> T;
while (T--) {
cin >> N;
for (int i = 1; i <= N; i ++ )cin >> a[i] >> p[i];
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= N; i++) {
int cnt = inf, sum = 0;
for (int j = i; j > 0; j--) {
sum += a[j];
cnt = min(cnt, dp[j - 1] + (sum + 10)*p[i]);
}
dp[i] = cnt;
}
cout << dp[N] << endl;
}
}