算法分析與設計課程作業第八週#1

算法分析與設計課程作業第八週#1

這周選了道leetcode上有關線性規劃的hard題來做,選了之後仔細看才發現題目的思路與課上講的矩陣鏈式相乘幾乎一模一樣。以下是題目:

312. Burst Balloons

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
Example:
Given [3, 1, 5, 8]
Return 167

nums = [3,1,5,8] –> [3,5,8] –> [3,8] –> [8] –> []
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

思路

考慮添加兩個均爲1的氣球(如題目提示),記錄到數組ballons[size]中去。
將ballons中元素兩兩形成一個矩陣,ballons[0],ballons[1]作爲行數,列數形成矩陣1,ballons[i-1],ballons[i]作爲行數,列數形成矩陣i(i>0),如此類推,形成size-1個矩陣,問題變成求這些矩陣連乘所需要的最大代價(課堂上教授了求最小代價,但其實思路一樣)。
如此一來,可以建立矩陣c[size][size],c[i][j]表示矩陣i(行數爲ballons[i-1],列數爲ballon[i])乘到矩陣j(行數爲ballons[j-1],列數爲ballon[j])所需的最大代價(i,j不等於0)。c[i][i]=0,因爲添加兩個爲1的氣球在一頭一尾後考慮不存齊三個氣球不能引爆(這個考慮在不爆完所有原來的氣球前都是成立的),添加兩個爲1的氣球在一頭一尾就是爲了最後只剩一個或兩個氣球時(不包括一頭一尾爲1的氣球)也能爆。
然後,從j-i=1(兩個矩陣相乘,涉及3個ballons)開始到j-i=size-2(共有size-1個矩陣,i,j大於等於1小於等於size-1),計算從第i個矩陣到第j個矩陣相乘的最大代價,狀態轉移式如下:
c[i][j]=max{c[i][k]+c[k+1][j]+ballons[i-1]*ballons[k]*ballons[j]:i<=k<j}
這個狀態轉移式的意思是先乘i到k的矩陣(已計算最大代價),再乘k+1到j的矩陣(已計算最大代價),再將得到的結果相乘,將這三步的最大代價加起來,求k從i到j-1的這些所求值的最大值。
這樣,最後求出的c[1][size-1]即爲第一個矩陣乘到最後一個矩陣的最大代價,也即是從第一個氣球爆到最後一個氣球能得到的最大金幣數。

代碼

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        int size = nums.size();
        int ballons[size+2];
        ballons[0] = 1;
        ballons[size+1] = 1;
        for(int i = 0; i < size; i++){
            ballons[i+1] = nums[i];
        }
        size += 2;
        int c[size][size];//c[i][j] : maximum coins to burst ballons[i-1] to ballons[j]
        for(int i = 0; i < size; i++){
            for(int j = 0; j < size; j++){
                c[i][j] = 0;
            }
        }
        for(int s = 1; s <= size-2; s++){
            for(int i = 1; i <= size-1-s; i++){
                int j = i + s;
                for(int k = i; k < j; k++){
                    if(c[i][k] + c[k+1][j] + ballons[i-1]*ballons[k]*ballons[j] > c[i][j])
                        c[i][j] = c[i][k] + c[k+1][j] + ballons[i-1]*ballons[k]*ballons[j];
                }
            }
        }
        return c[1][size-1];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章