?
? ? ? ? //当我们将棍子分段之后,我们是不是想到了怎么组合这些棍子
? ? ? ? //并且这些棍子有一个性质就是只能与相邻的进行组合
? ? ? ? //暴力搜索的话复杂度很高
? ? ? ? //在思考暴力搜索的时候,我们发现一个规律
? ? ? ? //比如棍子长度1 2 1 1 2
? ? ? ? //那么与最后一个2组合的棍子有,1 2,1 1 2,2 1 1 2,1 2 1 1 2
? ? ? ? //与最后一个1组合的棍子有,1 1,2 1 1,1 2 1 1
? ? ? ? //发现一个很显然的规律,能与前面组合的只有前面已经组合过的才能组合在一起
? ? ? ? //这是左边,那么当然还有右边
? ? ? ? //同理也是
? ? ? ? //然后根据规律总结一下公式
? ? ? ? //假设1 2 1 1 2,下标对应0 1 2 3 4
? ? ? ? //设f[i][j],表示组成这个区间的棍子的成本
? ? ? ? //那么想组成f[0][4] = f[0][3] + a[4];
? ? ? ? //f[1][4] = f[1][3] + a[4];
? ? ? ? //f[2][4] = f[2][3] + a[4];
? ? ? ? //f[3][4] = f[3][3] + a[4];
? ? ? ? //从这里又能看出我们组合肯定是根据范围从小到大进行组合的
? ? ? ? //比如f[1][3] = f[1][2] + f[2][3];那么在统计范围大的区间时
? ? ? ? //是由前面一个小范围推过来的,所以故此在计算大范围之前先统计小范围
? ? ? ? //故这就是动态规划的阶段
? ? ? ? //本题中我们求的是最小成本,那么需要把所有能组成f[0][4]的最小成本在推导时取个min就可以了
class Solution {
public:
int minCost(int n, vector<int>& cuts)
{
sort(cuts.begin(),cuts.end());
vector<int> a;
int prev = 0;
for(int i = 0;i < cuts.size();i++)
{
a.push_back(cuts[i] - prev);
prev = cuts[i];
}
a.push_back(n - prev);
//当我们将棍子分段之后,我们是不是想到了怎么组合这些棍子
//并且这些棍子有一个性质就是只能与相邻的进行组合
//暴力搜索的话复杂度很高
//在思考暴力搜索的时候,我们发现一个规律
//比如棍子长度1 2 1 1 2
//那么与最后一个2组合的棍子有,1 2,1 1 2,2 1 1 2,1 2 1 1 2
//与最后一个1组合的棍子有,1 1,2 1 1,1 2 1 1
//发现一个很显然的规律,能与前面组合的只有前面已经组合过的才能组合在一起
//这是左边,那么当然还有右边
//同理也是
//然后根据规律总结一下公式
//假设1 2 1 1 2,下标对应0 1 2 3 4
//设f[i][j],表示组成这个区间的棍子的成本
//那么想组成f[0][4] = f[0][3] + a[4];
//f[1][4] = f[1][3] + a[4];
//f[2][4] = f[2][3] + a[4];
//f[3][4] = f[3][3] + a[4];
//从这里又能看出我们组合肯定是根据范围从小到大进行组合的
//比如f[1][3] = f[1][2] + f[2][3];那么在统计范围大的区间时
//是由前面一个小范围推过来的,所以故此在计算大范围之前先统计小范围
//故这就是动态规划的阶段
//本题中我们求的是最小成本,那么需要把所有能组成f[0][4]的最小成本在推导时取个min就可以了
//1 2 1 1 2
int f[110][110];
memset(f,0x3f3f3f3f,sizeof(f));
vector<int> b(a.size() + 1);
for(int i = 0;i < a.size();i++) b[i + 1] = a[i];
for(int i = 1;i <= a.size();i++) f[i][i] = 0;
int s[110];
memset(s,0,sizeof(s));
for(int i = 1;i <= a.size();i++) s[i] = s[i - 1] + b[i];
for(int len = 2;len <= a.size();len++)//枚举的范围和阶段
{
for(int l = 1;l + len - 1<= a.size();l++)//确定范围,把当前阶段的状态都枚举出来
{
int r = l + len - 1;
for(int k = l;k < r;k++)//确定好范围之后,我们就可以更新当前范围的状态了
//怎么样保证不漏掉呢,只要枚举l <= k < r之间的k就行,可以保证所有状态都有
{
f[l][r] = min(f[l][r],f[l][k] + f[k + 1][r] + s[r] - s[l - 1]);
}
}
}
return f[1][a.size()];
}
};