题目: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; }