在王者荣耀充皮肤时,我们通常会面临一些问题:在已有的点券下,如何充值最少得到心仪的皮肤,此时很显然连续多次充1块的最划算,但是反复充值很多次很麻烦,浪费时间。此时我们的需求就是在花费最少的条件下,使充值的次数最少。
假设我已有点券数100个,想要充一个传说皮肤,也就是得要1688点券,充值框只有11个选项,设每个选项充值xi(i=1,2,...,11)次 ,可以建立以下数学模型:
经常学运筹学的小伙伴们都知道,以上问题在数学上称为多目标整数规划,接着我将借助MATLAB中的gamultiobj这一函数来实现求解,代码如下 :
%%多目标规划
clear;clc;
FitnessFunction = @funn;
number = 11;
ticket_now = 100;%已有点券数
ticket_pre = 1688;%期望点券数
ticket = ticket_pre-ticket_now;%待支付点券数
A = -10*[1,6,18,30,68,118,198,348,648,898,1298];
b = -1*ticket;
Aeq = [];
beq = [];
lb = zeros(1,11);%最少买0个
ub = [];
intcon = [1,2,3,4,5,6,7,8,9,10,11];
[x,fval] = gamultiobj(FitnessFunction,number,A,b,Aeq,beq,lb,ub,[],intcon,[]);
idx = find(fval(:,1)==min(fval(:,1)));
if size(idx)~=1
idx = find(fval(:,2)==min(fval(:,2)));
else
idx = idx(1);
end
disp(['最小花费',num2str(fval(idx,1)),'人民币']);
for i = 1:11
if x(idx,i)~=0
disp([num2str(i),'号点券买',num2str(x(idx,i)),'个']);
end
end
function y = funn(x)
y(1) = 1*x(1)+6*x(2)+18*x(3)+30*x(4)+68*x(5)+118*x(6)+198*x(7)+348*x(8)+648*x(9)+898*x(10)+1298*x(11);%付得少
y(2) = x(1)+x(2)+x(3)+x(4)+x(5)+x(6)+x(7)+x(8)+x(9)+x(10)+x(11);%次数少
end
运行结果如下图:
因此已有点券数100个,想要充一个传说皮肤,最少也得花159元,且最合适的充值方案是:1号点券买1个,2号点券买2个,3号点券买1个,4号点券买2个,5号点券买1个。