题目:http://www.razxhoi.com/mod/programming/view.php?id=5444
【题目描述】收购魔法石(pearls.cpp/c/pas)ZJU 1563

由于魔法石的巨大消耗,魔法学院需要购买不同等级的魔法石,有高等级也有低等级,每个等级有一定的价钱。每一次买一种等级的魔法石,必须多买10个。 为了节约用钱,魔法学院会采取如下的方法:比如,需要买5颗1等级(低)的魔法石,每颗10 元,100颗2等级(高)的魔法石,每颗20元。如果每个等级都买到需要:(5+10)×10+(100+10)×20=2350 元。但如果不买低等级的魔法石而换买高等级的,则用钱为(5+100+10)×20=2300元,这样就省钱了!

要求输出买所有的魔法石(可以把低等级的换买高等级的,但不能把高等级的换买低等级的)需要花费的最少钱数。

【输入格式】

第一行包含一个数字N,即有N组测试数据。每组测试数据的行数由c (1 ≤ c ≤ 100)来决定,c行中的每一行都包含两个数字ai 和 pi,第一个数字表示需要的魔法石数 (1≤ai ≤1000),第二个数字表示该类魔法石的价值(1≤ pi ≤ 1000)。魔法石的品质由低至高严格按顺序给出。所有数字均为整数。

【输出格式】

每组测试数据输出一行,每行均为最少钱数。

【输入样例】
2
100 1
100 2

【输出样例】
330

题解:这道题是一道动态规划问题, 我们设dp[i]表示从前i种魔法石购买的最小钱数,可以推出:如果用第i+2种魔法石去代替第i种魔法石的话,肯定可以用第i+1种魔法石去代替第i种魔法石(因为品质(价值)从低到高按顺序给出),可推出公式:dp[i]=min(dp[i],dp[j]+(10+c[i]-c[j])*b[i]);1<=i<=n,0<=j<i;
c[i]是求前i种的魔法石之和;

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,a[10005],b[10005],dp[10005],c[10005];
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    freopen("pearls.in","r",stdin);
    freopen("pearls.out","w",stdout);
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
        c[i]=c[i-1]+a[i];
    }
    memset(dp,127/3,sizeof(dp));//清成最大值,防止出错。
    dp[0]=0;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<i;j++)
        {
            dp[i]=min(dp[i],dp[j]+(10+c[i]-c[j])*b[i]);
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}