从王者荣耀氪金到动态规划

问题如下
王者荣耀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。

//觉得有用的大佬请带我上分

posted @ 2020-05-01 18:34  C_hp  阅读(393)  评论(1编辑  收藏  举报