階梯形算法(cascade algorithm)[1] 是用於求解雙尺度差分方程的逼近算法。
以上是官方的解釋,不明覺厲。
我們還是舉個栗子吧:
比如:
0-500 度 ==》 收費價格是 0.5元 定額內
500-800度 ==》 收費價格是 0.8元 第一階梯
800-1000度 ==》 收費價格是 1.2元 第二階梯
1000度以上 ==》 收費價格是1.5元 第三階梯
當用戶已經用了200度的時候,再購買700 度的時候,需要支付多少錢?
剛開始遇到這個問題的時候,第一反應就是,先判斷 在哪個階梯,然后比較大小,然后就沒有然后了,發現,會有很多種情況,這里還只是 三個階梯,假設有很多
階梯的情況下,會 go die 的,所以,后來想看看能不能用算法來解決,
思路: 從最高階梯開始循環, 用(總量(當前值+購買值)-最高階梯最低值) 與 購買值 進行相減 >0,則 處於最高階梯的 直接取購買值,<0,則 取 (總量(當前值+購買值)-最高階梯最低值)
循環到下一個階梯時, 用 剩余值(購買值-上一階梯的取值)與 這個階梯的區域差值進行相減 >0,則 處於這一階梯的 取值為 區域差值,<0,則 取 剩余值
以此類推
我這里是用java 的語法,話不多說,直接上代碼:
public class AreaValueUtil {
public static void main(String[] args) {
double currentMount=200;
double needMount=100;
// double priceArrs[]={0.5d,0.8d,1.2d,1.5d}; // 每個階梯的單價
double mountArrs[]={0,500,800,1000}; // 每個階梯的最小值
double[] valueArrs=new double[4]; // 存儲每個階梯對應的值
getAreaValue(mountArrs,valueArrs,currentMount,needMount);
System.out.println(valueArrs[0]+","+valueArrs[1]+","+valueArrs[2]+","+valueArrs[3]);
}
/**
*
*
* @param mountArrs 每個階梯量的最小值 ** 這里注意
* @param valueArrs 存儲每個階梯對應的值 (區域單價*區域量)
* @param currentMount 當前使用電量
* @param needMount 還需要電量
*/
public static double[] getAreaValue(double[] mountArrs,double[] valueArrs,double currentMount,double needMount){
int grade=valueArrs.length-1;
double gap=mountArrs[grade];;
double finalvalue=currentMount+needMount;
double leftvale=needMount;
boolean flag=false;
for(int i=grade;i>=0;i--){
if(i==0){
if(flag){
//總每個階段的錢
valueArrs[i]=finalvalue;
}else{
//購買的每個階段的錢
valueArrs[i]=leftvale;
}
break;
}
//剩下的=總-每個階段的電量
double tempvalue=finalvalue-gap;
if(tempvalue>0){
if(flag){ // 說明之前已經 減掉了部分
valueArrs[i]=gap;
finalvalue=leftvale-gap;
}else{
if(tempvalue>leftvale){
valueArrs[i]=leftvale;
break;
}else{
finalvalue=leftvale-tempvalue;
valueArrs[i]=tempvalue;
flag=true;
}
}
leftvale=finalvalue;
gap=mountArrs[i]-mountArrs[i-1];
}else{
if(flag){
valueArrs[i]=finalvalue;
break;
}else{
valueArrs[i]=0;
gap=mountArrs[i-1];
}
}
}
return valueArrs;
}
}
valueArrs里面就存儲了 每個階梯所對應的電量,在根據每個階梯的單價,相乘相加就可以了,這里最好用bigDecimal 來精確計算。
可能有什么不對的地方,望大家及時糾正指教!