题意
按顺序经过nnn个星球,有两种种类的星球:
(ppp为当前钻头能力值,初始能力为www)
1.资源型:含矿物质量a[i],若选择开采,则得到a[i]∗pa[i]*pa[i]∗p的金钱,之后钻头损耗k%,即p=p∗(1−0.01k)k\%,即p=p*(1-0.01k)k%,即p=p∗(1−0.01k)
2.维修型:维护费用b[i],若选择维修,则支付b[i]∗pb[i]*pb[i]∗p的金钱,之后钻头修复c%,即p=p∗(1+0.01c)c\%,即p=p*(1+0.01c)c%,即p=p∗(1+0.01c)
求出最多获得的金钱(金钱可透支)。
思路
显然可以看出是一道动态规划,不过从前往后枚举会有后效性,所以考虑从后往前枚举。
设f[i]f[i]f[i]为到当前星球的最多获得的金钱,可得:
f[i]=max(f[i+1],x[i]+f[i+1]∗(1−0.01∗k))f[i]=max(f[i+1],x[i]+f[i+1]*(1-0.01*k))f[i]=max(f[i+1],x[i]+f[i+1]∗(1−0.01∗k))
f[i]=max(f[i+1],f[i+1]∗(1+0.01∗c)−x[i])f[i]=max(f[i+1],f[i+1]*(1+0.01*c)-x[i])f[i]=max(f[i+1],f[i+1]∗(1+0.01∗c)−x[i])
表示选或不选择这个星球,或如果选择,会对后面的值产生影响。
代码
#include<cstdio>
#include<algorithm>
int type[100001], x[100001];
int n, k, c, w;
double f[100001];
int main() {
scanf("%d %d %d %d", &n, &k, &c, &w);
for (int i = 1; i <= n; i++)
scanf("%d %d", &type[i], &x[i]);
for (int i = n; i >= 1; i--) {
if (type[i] == 1) f[i] = std::max(f[i + 1], x[i] + f[i + 1] * (1 - 0.01 * k));
else f[i] = std::max(f[i + 1], f[i + 1] * (1 + 0.01 * c) - x[i]);
}
printf("%.2lf", f[1] * w);
}
博客围绕按顺序经过n个星球的问题展开,星球分资源型和维修型。资源型开采获金钱且钻头损耗,维修型维修付费用且钻头修复。采用动态规划求解最多获得的金钱,因从前往后枚举有后效性,故从后往前枚举,并给出状态转移方程。
2018

被折叠的 条评论
为什么被折叠?



