算法分析与设计课程作业第八周#1

来源:互联网 发布:无忧商务推广软件 编辑:程序博客网 时间:2024/05/22 00:23

算法分析与设计课程作业第八周#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];    }};
原创粉丝点击