P1412 经营与开发
P1412 经营与开发
题解
QWQ题外话(蒟蒻的心路历程):拿到这个题,这不DP吗!!然后开始DFS ----> 敲完开始考虑DP,正推退不动啊,头疼的P咋整啊 ----> 交上DFS代码----->爆零
DP大法好啊
考虑顺次走1~n 这些星球对吧,每个星球可以考虑采矿/修复,或者打酱油,那么一旦采矿/修复,就会改变收入,改变能力值 p ,所以说正推从 1~n 是不合适的,有后效性
then give up
正难则反啊!倒着推不就没有后效性了吗
解释一下:
假设你每个星球都开采,并且每个星球都是资源型,那么你最后的答案一定是这样:
w * a1 + w*(1-0.01k) *a2 + w*(1-0.01k)*(1-0.01k) * a3 + w*(1-0.01k)*(1-0.01k)*(1-0.01k) * a4.....
(提取一下公因式)
=w * ( a1 + a2*(1-0.01k) + a3*(1-0.01k)*(1-0.01k) + a4*(1-0.01k)*(1-0.01k)*(1-0.01k)......)
(秦九韶公式来一波)
=w * ( a1 + (1-0.01k) * ( a2 + (1-0.01k) * ( a3 + (1-0.01k) * ( a4 + (1-0.01k) * (......))))))
(方便起见我们用 kk 表示 (1-0.01k))
=w * ( a1 + kk * ( a2 + kk * ( a3 + kk * ( a4 + kk * (......))))))
so,你会发现:wow非常nice的秦九韶公式!!!
其实你最终的答案并不一定是每个星球都要开采,因此可能会缺几项,但这并不影响,而且每个星球也并不一定都是资源型,还可能是维护型,这样的话无非是把 (1-0.01k) 变成 (1+0.01c) ,也不会有啥影响
所以我们发现从后往前推是不会有后效性的,因为秦九韶计算也是从里到外计算
那么就是从 n 往前枚举,f[ i ] 表示从 星球 i 出发到达星球 n 的最大收入,ans is f[ 1 ]
得到递推式:
注意区分不同的类型,不同类型的星球造成的影响不同
代码
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=1e5+10; int n,k,c,w; int x[maxn],type[maxn]; double ans; double f[maxn]; int main() { n=read();k=read();c=read();w=read(); for(int i=1;i<=n;i++) { type[i]=read(); x[i]=read(); } for(int i=n;i>0;i--) { if(type[i]==1) f[i]=max(f[i+1],x[i]+f[i+1]*(1-0.01*k)); else f[i]=max(f[i+1],-x[i]+f[i+1]*(1+0.01*c)); } printf("%.2lf",f[1]*w); return 0; }