编程之美 - 1.6 饮料供货 ☞ 【动态规划】

问题导读:


在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?No,是去水房拿饮料:酸奶,豆浆,绿茶、王老吉、咖啡、可口可乐……(当然,还是有很多同事把拿饮料当做第二件事)。


管理水房的阿姨们每天都会准备很多的饮料给大家,为了提高服务质量,她们会统计大家对每种饮料的满意度。一段时间后,阿姨们已经有了大批的数据。某天早上,当实习生小飞第一个冲进水房并一次拿了五瓶酸奶、四瓶王老吉、三瓶鲜橙多时,阿姨们逮住了他,要他帮忙。


从阿姨们统计的数据中,小飞可以知道大家对每一种饮料的满意度。阿姨们还告诉小飞,STC(Smart Tea Corp.)负责给研究院供应饮料,每天总量为V。STC很神奇,他们提供的每种饮料之单个容量都是2的方幂,比如王老吉,都是23=8升的,可乐都是25=32升的。当然STC的存货也是有限的,这会是每种饮料购买量的上限。统计数据中用饮料名字、容量、数量、满意度描述每一种饮料。


那么,小飞如何完成这个任务,求出保证最大满意度的购买量呢?


解决方案:


    package Chapter1;
     
    import java.io.*;
     
    public class Func_1_6_1 {
        public static void main(String []args) {
            Func_1_6_1 f = new Func_1_6_1();
            Beverage []beverages = f.getData("/data/BeautyProgramming/Func_1_6_1.txt");
            System.out.println(f.digitSatisfy(beverages, 7));
        }
        /*
        Opt(v`,i) 为从i到最后一种饮料中,算出总量为v`的最大满意度之和
        Opt = max{
            k*Hi + Opt(v` - vi*k, i+1)
        }
         */
        // volume时最大满意度
        int digitSatisfy(Beverage []beverages, int volume) {
            // 如果beverages 没有数据,或者volume为0 直接返回 -1
            if (beverages == null || beverages.length == 0 || volume == 0) {
                return -1;
            }
     
            //创建opt数组
            int v = volume;
            int t = beverages.length;
            int [][]opt = new int[v+1][t+1];
     
            //初始化opt
            int INF = 1000;
            opt[0][t] = 0;
            for (int i = 1; i <= v; i++) opt[i][t] = -INF; // 边界
            for (int i = t-1; i >= 0; i--) {
                int mark = beverages[i].mark;
                int content = beverages[i].content;
                int count = beverages[i].count;
                // 体积
                for (int j = 0; j <= v; j++) {
                    opt[j][i] = -INF; // 相对边界
                    // max
                    for (int k = 0; k <= count; k++) {
                        if (j < k*content) break;
                        int x = opt[j-k*content][i+1] + mark*k;
                        if (x >= opt[j][i]) opt[j][i] = x;
                    }
                }
            }
            /*
            装不满:
            3
            1 4 2
            2 4 3
            3 4 4
             */
            int res = -INF;
            for (int []i : opt)
                res = i[0] > res ? i[0] : res;
            return res; // 状态转移公式的最外层结果
        }
        // 饮料
        class Beverage {
            int mark; // 打分
            int content; // 容量
            int count; // 数量
     
            public Beverage(int mark, int content, int count) {
                this.mark = mark;
                this.content = content;
                this.count = count;
            }
        }
        // 将string 转int
        int[] parseInt(String []str) {
            int []res = new int[str.length];
            for (int i = 0; i < str.length; i++) {
                res[i] = Integer.parseInt(str[i]);
            }
            return res;
        }
        // 得到data
        Beverage[] getData(String file_path) {
            Beverage []beverages;
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(
                        new InputStreamReader(
                                new FileInputStream(
                                        new File(file_path))));
                String line = null;
                String []str;
                int []digit;
     
                int total = Integer.parseInt(reader.readLine());
     
                beverages = new Beverage[total];
                for (int i = 0; i < total; i++) {
                    if ((line = reader.readLine()) != null) {
                        str = line.split(" ");
                        digit = parseInt(str);
                        int mark = digit[0];
                        int content = digit[1];
                        int count = digit[2];
                        beverages[i] = new Beverage(mark, content, count);
                    }
                }
                return beverages;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }


9
2 1 2
3 1 2
5 1 3
4 1 3
6 2 2
5 2 3
4 2 4
18 4 1
12 4 2


33
---------------------
作者:PeersLee
来源:CSDN
原文:https://blog.csdn.net/peerslee/article/details/77418065
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-07-19 11:57  天涯海角路  阅读(99)  评论(0)    收藏  举报