从王者荣耀氪金到动态规划
问题如下
王者荣耀5.1~5.5孙悟空皮肤至尊宝限时返场,价值88元人民币,现在为了购买这款皮肤,要充值90元人民币。
与此同时,天美为了鼓励玩家充值,推出充值活动,在5.1~5.5期间每日累计充值充值金额m
1<=m<6,赠送1个皮肤碎片和30积分;
6<=m<30,赠送2个皮肤碎片和30积分;
30<=m,赠送3个皮肤碎片和一张积分夺宝卷;
(即,冲值6块即可获得3个皮肤碎片,60积分,充值30块获得6皮肤碎片,60积分,1积分夺宝卷)
在游戏内可以用积分和夺宝卷进行抽奖,即可将积分和夺宝卷转换为皮肤碎片。
使用积分抽新品皮肤,每次消耗20积分,获得皮肤、皮肤体验卡和皮肤碎片
概率如下
(这里忽略掉英雄,这是另一款抽奖,另外,当抽中皮肤碎片时,可能为1个,也可能为2个,出现2个的概率是1个的两倍。)
使用积分夺宝卷进行抽奖,每次消耗一张夺宝卷
获得物品概率如下
(抽中英雄碎片和皮肤碎片等概)
现在问题如下,5.1~5.5期间如何充值这90人民币(充值金额为正整数),可使得获得的皮肤碎片的期望值最大?最大为多少?
这是一道动态规划的问题,虽然充值金额固定,但是不同类型的充值获得的物品不同,则其获得的皮肤碎片不同。
首先,我将抽奖设为三个档次,a,b,c,充值金额为m=90。a<6,6<=b<30,c>=30,显然 1<=a+b+c<=5
由于c为充值金额最大,其最多充值3次即可达到题目要求,那么我们就按c的个数来统计充值方式。
①c=3时,仅存在 (c,c,c)一种充值方式
②c=2时,
(c,c)
(c,c,a),(c,c,b)
(c,c,a,a)(c,c,a,b)(c,c,b,b)
(c,c,a,a,a)(c,c,a,a,b)(c,c,a,b,b)(c,c,b,b,b)
③c=1时,
(c)
(c,a)(c,b)
(c,a,a)(c,a,b)(c,b,b)
(c,a,a,a)(c,a,a,b)(c,a,b,b)(c,b,b,b)
(c,a,a,a,a)(c,a,a,a,b)(c,a,a,b,b)(c,a,b,b,b)(c,b,b,b,b)
④c=0时
(b,b,b,b)(b,b,b,a)
(b,b,b,b,b)(b,b,b,b,a)(a,a,b,b,b)
通过上面的统计我们可以发现规律,当有c存在时,只需要满足 (m-(a+6b)) >=30c (你可以这样理解,当有c时,a,b随便选,只要剩余的钱 m-(a+6b) 足够充值整数个c即可),当没有c存在时则必须满足 (m-5a) <= 29b
思路如上,代码如下
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
#define $ 90 //题目要求的充值金额
class SFs
{
public:
void Func(int a, int b, int c)
{
int sf = a+3*b+6*c,count = a*30+(b+c)*60;
float average = sf+count/20*0.907*5/3+c*0.317*0.5;
if(average > 30)//将平均值大于30的以红色打印
printf("\033[31m皮肤碎片%d,%d积分,%d积分夺宝卷。获得皮肤碎片的期望值为%f \n\033[0m", sf, count, c, average);
else
cout<<sf<<"皮肤碎片,"<<count<<"积分,"<<c<<"积分夺宝卷。"<<"获得皮肤碎片的期望值为"
<<average<<endl;
}
};
class solu
{
public:
void Func()
{
SFs sf;
for(int c=0; c<=3; ++c)
{
for(int b=0; b<=5; ++b)
{
for(int a=0; a<=4; ++a)
{
if(a+b+c>=1 && a+b+c<=5)//基础条件
{
if(c > 0)
{
if($-(6*b+a) >= 30*c)
{
for(int i=a; i>0; --i)
cout<<'a';
for(int i=b; i>0; --i)
cout<<'b';
for(int i=c; i>0; --i)
cout<<'c';
cout<<" = ";
sf.Func(a, b, c);
}
else
continue;
}
else
{
if($-a*5 <= 29*b)
{
for(int i=a; i>0; --i)
cout<<'a';
for(int i=b; i>0; --i)
cout<<'b';
for(int i=c; i>0; --i)
cout<<'c';
cout<<" = ";
sf.Func(a, b, c);
}
else
continue;
}
}
}
}
}
return;
}
};
int main()
{
solu res;
res.Func();
return 0;
}
跑了一下试试
得出最佳充值方式为bbbcc,即5天内两天充值30档次,三天充值6档次,总共充值足够90即可(如,30,30,6,618)得皮肤碎片的平均值为43.99。
//觉得有用的大佬请带我上分