小奇挖矿 解题报告

小奇挖矿

【题目背景】

    小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过喵星系的n个星球。

【问题描述】

    星球分为2类:资源型和维修型。
    1.资源型:含矿物质量a[i],若选择开采,则得到a[i]p的金钱,之后钻头损耗k%,即p=p(1-0.01k)
    2.维修型:维护费用b[i],若选择维修,则支付b[i]p的金钱,之后钻头修复c%,即p=p(1+0.01c)
    (p为钻头当前能力值)
    注:维修后钻头的能力值可以超过初始值
    请你帮它决策最大化这个收入

【输入格式】

    第一行4个整数n,k,c,w。
    以下n行,每行2个整数type,x。
    type为1则代表其为资源型星球,x为其矿物质含量a[i];
    type为2则代表其为维修型星球,x为其维护费用b[i];

【输出格式】


    输出一行一个实数(保留两位小数),表示要求的结果。

【样例输入】

    5 50 50 10
    1 10
    1 20
    2 10
    2 20
    1 30

【样例输出】

    375.00

【数据范围】

    对于30%的数据 n<=100
    对于50%的数据 n<=1000,k=100
    对于100%的数据 n<=100000,0<=k,c,w,a[i],b[i]<=100

    保证答案不超过10^9.


因为题目要求依次飞过各星球,所以可以考虑dp。

而这题dp最重要的是:倒着dp(有篇解题报告讲得很好:http://blog.csdn.net/ocacs1/article/details/52654491);我这里就讲讲如何推这个状态转移方程吧。

设dp[i]表示i到n的最大收益,若此时倒着dp到第i-1个星球,以资源型星球为例,设i-1个星球的钻头能力值为1(这里是相对能力值,可看作100%),那么若是选择不挖,dp[i-1]=dp[i];否则,能力值减少0.01k,同时获得x[i-1]*1(相对能力值为1)的收益,因为收益受p(能力值)的影响且两者成正比(因为不管是收益,还是支付,都是x[i]*p的费用),故dp[i]会相对地减少0.01k,即dp[i-1]=dp[i]*(1-0.01k)+x[i-1];故dp方程为:

dp[i-1]=max(dp[i],dp[i]*(1-0.01*k)+x[i-1]);

同理,对于维修型星球,dp方程为:

dp[i-1]=max(dp[i],dp[i]*(1+0.01*k)-x[i-1]);

代码如下:

#include
#include
using namespace std;
	int n,k,c,w;
	double ans;
	int x[100001],type[100001];
	double dp[100001];
int main()
{
	freopen("explo.in","r",stdin);
	freopen("explo.out","w",stdout);
	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)
			dp[i]=max(dp[i+1],dp[i+1]*(1-0.01*k)+x[i]); //资源型
		else if (type[i]==2)
			dp[i]=max(dp[i+1],dp[i+1]*(1+0.01*c)-x[i]); //维修型
	printf("%.2lf",dp[1]*w);
	return 0;
}

你可能感兴趣的:(递推与动态规划)