题目大意
大致题意:
给出几类珍珠,以及它们的单价,要求用最少的钱就可以买到相同数量的,相同(或更高)质量的珍珠。
【规定买任一类的珍珠 n n n个(价格为 p p p),都要支付 ( n + 10 ) ∗ p (n+10)*p (n+10)∗p的钱,即额外支付 10 ∗ p 10*p 10∗p】
样例分析
例如样例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元
贪心为什么错
一开始想过从头到尾遍历珍珠的价格和数目,每次都看相临的两个,如果把当前这一批放入下一个等级价格降低,则将他放到下一个等级,否则直接算在当前等级的买的价格加到答案中,最后一等后设置最大值,保证不会再向后放.,但是这样的思路其实是错误的,以下是证明:
价格
p
a
<
p
b
<
p
c
pa<pb<pc
pa<pb<pc
假设贪心得出
(
a
+
10
)
p
a
>
a
∗
p
b
(a+10)pa>a*pb
(a+10)pa>a∗pb和
(
a
+
b
+
10
)
p
b
>
(
a
+
b
)
∗
p
c
(a+b+10)pb>(a+b)*pc
(a+b+10)pb>(a+b)∗pc两个前提
但是对于
(
a
+
10
)
∗
p
a
+
(
b
+
c
+
10
)
∗
p
c
<
(
a
+
b
+
c
+
10
)
∗
p
c
(a+10)*pa+(b+c+10)*pc<(a+b+c+10)*pc
(a+10)∗pa+(b+c+10)∗pc<(a+b+c+10)∗pc即不采取归并更小的情况是否存在呢
化简式子:
(
a
+
10
)
∗
p
a
<
(
a
+
b
)
∗
p
c
(a+10)*pa<(a+b)*pc
(a+10)∗pa<(a+b)∗pc
对比条件,我们知道 ( a + 10 ) ∗ p a > a ∗ p b 和 ( a + b + 10 ) p b > ( a + b ) ∗ p c (a+10)*pa>a*pb和(a+b+10)pb>(a+b)*pc (a+10)∗pa>a∗pb和(a+b+10)pb>(a+b)∗pc
完全可以有 a ∗ p b < ( a + 10 ) ∗ p a < ( a + b ) ∗ p c < ( a + b + 10 ) ∗ p b a*pb<(a+10)*pa<(a+b)*pc<(a+b+10)*pb a∗pb<(a+10)∗pa<(a+b)∗pc<(a+b+10)∗pb
所以贪心策略是错的
为什么可以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.不存在断点,即所有的都用最大一种替换,
d
p
[
c
]
=
(
a
[
1
]
+
.
.
.
+
a
[
c
]
+
10
)
∗
p
[
c
]
dp[c]=(a[1]+...+a[c]+10)*p[c]
dp[c]=(a[1]+...+a[c]+10)∗p[c]
2.存在断点,最后一个断点为i,那么最优解必为
d
p
[
i
]
+
(
a
[
i
+
1
]
+
.
.
+
a
[
c
]
+
10
)
∗
p
[
c
]
dp[i]+(a[i+1]+..+a[c]+10)*p[c]
dp[i]+(a[i+1]+..+a[c]+10)∗p[c]
每个点都有可能是最后一个断点,因此产生了我们的DP方程:
d
p
[
i
]
=
m
i
n
(
d
p
[
j
]
+
(
a
[
j
+
1
]
+
.
.
+
a
[
i
]
+
10
)
∗
p
[
i
]
)
dp[i]=min(dp[j]+(a[j+1]+..+a[i]+10)*p[i])
dp[i]=min(dp[j]+(a[j+1]+..+a[i]+10)∗p[i])
把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;
}
}