重学动态规划

写在前面的话:之前没好好学动态规划,现在开始再重新学一遍吧!

1 买卖股票的最佳时机II

    // 简易的做法
    public int maxProfit(int[] prices) {
        // 这个题目隐含了可以,同一个股票卖了又买,所以
        // 1,2,3,4,5。5 - 1 = (2 - 1) + (3 - 2) + (4 - 3) + (5 - 4)
        if (prices == null || prices.length < 2) return 0;

        int n = prices.length;
        int ans = 0;
        for (int i = 1; i < n; i++) {
            ans += (prices[i] - prices[i - 1]) > 0 ? (prices[i] - prices[i - 1]) : 0;
        }

        return ans;
    }
    // 动态规划的写法
    [来自](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode-s/)
    public int maxProfit(int[] prices) {
        int n = prices.length;
        int [][]dp = new int[n][2];
        // 设置利润
        dp[0][0] = 0;
        // 表示买入第一支股票
        dp[0][1] = -prices[0];

        // 两种状态
        for (int i = 1; i < n; i++) {
            // 表示手里没有股票的最大利润
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
            // 表示手机持有一只股票的最大利润
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);

            /**
             * 其中这两段代码分别的意思为
             * 当前没有股票的最大利润 = Max(前一次无股最大利润,前一次有股最大利润 + 卖出股得利润)
             * 当前含有股票的最大利润 = Max(前一次含股最大利润,前一次无股最大利润 + 更新股票买入股票)
             */
        }

        return dp[n - 1][0];
    }
    
    
    

2 P1048 [NOIP2005 普及组] 采药

  public class Main {

    /**
     * 非常经典的题目
     * 现在的理解就是,比如空间为6,
     * 消耗了4空间,那么2空间中的价值为对应4空间的价值
     * 最重要的思想就是“覆盖”
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        int m = sc.nextInt();

        int [][]Herbs = new int[1000 + 5][2];
        for (int i = 0; i < m; i++) {
            Herbs[i][0] = sc.nextInt();
            Herbs[i][1] = sc.nextInt();
        }

        int []dp = new int[t + 5];
        for (int i = 0; i < m; i++) {
            System.out.println("---------" + Herbs[i][0] +"----"+ Herbs[i][1] +"---------");
            for (int j = t; j >= Herbs[i][0]; j--) {
                dp[j] = Math.max(dp[j],  dp[j - Herbs[i][0]] + Herbs[i][1]) ;
            }
        }
        System.out.println(dp[t]);
    }
}

/** 7 4
 * ---------5----4---------
 * 第一次进行赋值,无需进行比较,直接赋值
 * dp[7] = 4 = Max(dp[7], dp[2] + 4)
 * dp[6] = 4 = Max(dp[6], dp[1] + 4)
 * dp[5] = 4 = Max(dp[5], dp[0] + 4)
 * 后面进行的赋值,Max(原对应空间拥有的价值,剩下空间X(遍历V-> X,V - x) + 当前物品的价值)
 * 主要是后面这一句,剩下空间X(遍历V-> X,V - x) + 当前物品的价值
 * 这里成就了动态更新对应空间的最大价值,剩下的空间对应的价值 + 原空间对应的价值。
 * 比如,5会考虑到 2,1,0
 *      2会考虑到 5,4,3,2,1,0
 *      这样就形成了“覆盖叠加”
 * 
 * ---------3----2---------
 * 
 * dp[7] = 4 = Max(dp[7], dp[4] + 2)
 * dp[6] = 4 = Max(dp[6], dp[3] + 2)
 * dp[5] = 4 = Max(dp[5], dp[2] + 2)
 * dp[4] = 2 = Max(dp[4], dp[1] + 2)
 * dp[3] = 2 = Max(dp[3], dp[0] + 2)
 * ---------2----1---------
 * dp[7] = 5 = Max(dp[7], dp[5] + 1)
 * dp[6] = 4 = Max(dp[6], dp[4] + 1)
 * dp[5] = 4 = Max(dp[5], dp[3] + 1)
 * dp[4] = 2 = Max(dp[4], dp[2] + 1)
 * dp[3] = 2 = Max(dp[3], dp[1] + 1)
 * dp[2] = 1 = Max(dp[2], dp[0] + 1)
 * ---------3----4---------
 * dp[7] = 6 = Max(dp[7], dp[4] + 4)
 * dp[6] = 6 = Max(dp[6], dp[3] + 4)
 * dp[5] = 5 = Max(dp[5], dp[2] + 4)
 * dp[4] = 4 = Max(dp[4], dp[1] + 4)
 * dp[3] = 4 = Max(dp[3], dp[0] + 4)
 *
 */

《算法竞赛入门经典第二版》
posted @ 2020-11-26 09:39  Bears9  阅读(98)  评论(2编辑  收藏  举报