注意一点:
如果第 i 种珍珠用第 j 种珍珠代替得到最优解, 那么第 i+1~ j - 1种珍珠都应该由第 j 种珍珠代替。
证明:由已知可得第 j 种珍珠一定会买,所以第 i+1~ j - 1种珍珠由 j 以后的珍珠代替不能得到最优,若第 i+1~ j - 1种珍珠
不由第 j 种代替,那么在第 i+1~ j - 1种珍珠之间必定要买至少一种珍珠 k,那么将第 i 种珍珠由第 k 种珍珠代替,得到
的解比第 i 种珍珠用第 j 种珍珠代替更优,这与已知矛盾,所以第 i+1~ j - 1种珍珠都应该由第 j 种珍珠代替。
只需确定第 i 种珍珠之前连续几种珍珠由 i 种珍珠代替。
所以得到状态转移方程 dp[ i ] = min ( dp[ i ], dp[ j ] + ( sum[ i ] - sum[ j ] + 10 ) * cost[ i ] )
其中dp[ i ] 表示买前 i 种珍珠所花的最少钱
sum[ i ] 表示前 i 种珍珠一共要买多少颗
cost[ i ]为第 i 种珍珠的单价。
#include <iostream>
#include <cstdio>
using namespace std;
#define M 105
#define INF 999999999
int c, cost[M], need[M], sum[M], dp[M];
inline int min(int a, int b)
{
return a < b ? a : b;
}
int DP()
{
int i, j;
dp[0] = 0;
for (i = 1; i <= c; i++) {
dp[i] = INF;
for (j = 0; j <= i; j++)
dp[i] = min (dp[i], dp[j] + (sum[i] - sum[j] + 10) * cost[i]);
}
return dp[c];
}
int main()
{
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d", &c);
need[0] = cost[0] = sum[0] = 0;
for (int i = 1; i <= c; i++) {
scanf ("%d %d", &need[i], &cost[i]);
sum[i] = sum[i-1] + need[i];
}
printf ("%d\n", DP());
}
return 0;
}