package inventory;


/**
 * Created on 18.04.2014 0:45:17
 *
 * @author Alexander Mikhailovich Kovshov
 */
public class InventoryModel {

    static int n = 8;                                               //число промежутков времени (месяцев)
    static int max = 10;                                            //наибольшее значение для остатка на складе
    static double[] inprice =   { 2,  3,  1,  6,  7, 10,  8,  6};   //цены закупочные за каждый месяц              
    static double[] outprice =  {15, 10,  9, 10, 20, 30, 20, 10};   //цены отпускные за каждый месяц            
    static double[] store =     { 1,  1,  1,  1,  1,  1,  1,  1};   //стоимость хранения единицы товара за каждый месяц
    static int[] need =         { 8,  7,  6,  7,  8,  7,  6,  7};   //потребность за каждый месяц
    static int[] add = new int[n];                                  //приобретение в каждом месяце

    static double[][] profit = new double[n][max + 1];              //Прибыль за каждый месяц и все последующие за ним месяцы в зависимости от остатка на начало месяца.
    static int[][] restFromProfit = new int[n][max + 1];            //Наилучший остаток на конец каждого месяца в зависимости от остатка на начало каждого месяца.

        
    public static void main(String[] args) {
                //Вычисление возможной прибыли за конечный (n-й) месяц в зависимости от остатка на складе.
                //r --- возможный остаток на складе от предыдущего месяца
        for (int r = 0; r <= max; r++) {
            int add_r = need[n - 1] - r; //Приобретение за конечный (n-й) месяц.
            if (add_r < 0) {
                profit[n -1][r] = Integer.MIN_VALUE;
                continue;
            }
            profit[n - 1][r] = 
                    outprice[n - 1] * need[n - 1] 
                    - inprice[n - 1] * add_r 
                    - store[n - 1] * ((double)r / 2); 

        }
        for (int m = n - 1; m > 0; m--) {

                    //Вычисление возможной прибыли за m-й месяц в зависимости от остатка на складе.
                    //r  --- возможный остаток на складе на начало месяца. 
                    //rr --- возможный остаток на складе на конец месяца.
            for (int r = 0; r <= max; r++) {
                profit[m - 1][r] = Integer.MIN_VALUE;
                for (int rr = 0; rr <= max; rr++) {
                    //Прибыль за m-й и последующие месяцы в зависимости от остатка на конец месяца.
                                        double profitTemp;
                    //Приобретение за m-й месяц
                    int add_r = need[m - 1] + rr - r; 
                    if (add_r < 0) {
                                                profitTemp = Integer.MIN_VALUE; 
                    } else {
                        profitTemp =                    
                                    outprice[m - 1] * need[m - 1] 
                                    - inprice[m - 1] * add_r 
                                    - store[m - 1] * ((double)(r + rr) / 2) + profit[m][rr]; 
                    }
                    //Если данный остаток на конец месяца даёт наибольшую прибыль
                    //за этот и последующие месяцы при данном остатке на начало месяца,
                    //то значение прибыли и конечный остаток сохраняются.
                    if (profitTemp > profit[m - 1][r] ) {
                                                profit[m - 1][r] = profitTemp;
                                                restFromProfit[m - 1][r] = rr;
                    }       
                }

            }
        }
        System.out.println("=========== План закупок ===============");
        for (int m = 0, r = 0; m < n; m++) {
                        
                        System.out.println( (m + 1) 
                                        + "; Остаток на начало: " + r 
                                        + "; Остаток на конец: " + restFromProfit[m][r] 
                                        + "; Потребление: " + need[m] 
                                        + "; Закупки: " +  (need[m] - r + restFromProfit[m][r])
                        );
                        r = restFromProfit[m][r];
        }
        
    }
}