动态规划(一)
- 动态规划方法通产用来求解最优化问题
- 刻画一个最优解的结构特征
- 递归地定义最优解得值
- 计算最优解得值,通常采用自底向上的方法
- 利用计算出的信息构造一个最优解
- 使用情况:
- 具有重叠子问题
- 需要记录表
钢条切割
分治法
int cutRod(vector<int> &p,int n){
if (n==0) return 0;
int q=INT_MIN;
for(int i=0;i<n;i++)
q=max(q,p[i]+cutRod(p,n-i));
return q;
}
自顶向下的DP
int memoizedCutRod(vector<int> &p,int n){
vector<int> r(n+1,INT_MIN);
return memoizedCutRodAux(p,n,r);
}
int memoizedCutRodAux(vector<int> &p,int n,vector<int> &r){
if(r[n]>=0) return r[n];
int q;
if(!n) q=0;
else {
q=INT_MIN;
for(int i=0;i<n;i++)
q=max(q,p[i]+memoizedCutRodAux(p,n-i,r));
}
r[n]=q;
return q;
}
自底向上DP
int BottomUpCutRod(vector<int> &p,int n){
vector<int> r(n+1,0);
for(int j=0;j<n;j++){
int q=INT_MIN;
for(int i=0;i<j;i++)
q=max(q,p[i]+r[j-i]);
r[j]=q;
}
return r[n];
}
最优子结构
最长公共子序列 LCS
int LCS(string A, string B){
int m=A.length();
int n=B.lenght();
vector<vector<int>> c(m,vector<int>(n,0));
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(A[i-1]==B[j-1])
c[i][j]=c[i-1][j-1]+1;
else
c[i][j]=max(c[i-1][j],c[i][j-1]);
}
}
return c[m][n];
}
最长递增子序列
int lengthOfLIS(vector<int>& nums){
int len=nums.size();
if(len<=1) return len;
vector<int> r(len,1);
int longest=1;
for(int i=1;i<len;i++){
for(int j=0;j<i;j++){
if(nums[j]<nums[i])
r[i]=max(r[i],r[j]+1);
}
longest=max(longest,r[i]);
}
return longest;
}
最小路径和
int minPathSum(vector<vector<int>>& grid){
if(grid.empty()||!grid.size()||!grid[0].size())
return 0;
int m=grid.size();
int n=grid[0].size();
vector<vector<int>>& dp(m,vector<int>(n,0));
dp[0][0]=grid[0][0];
for(int i=1;i<m;i++)
dp[i][0]+=dp[i-1][0]+grid[i][0];
for(int j=1;j<n;j++)
dp[0][j]+=dp[0][j-1]+grid[0][j];
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=min(dp[i-1][j], dp[i][j-1])+ grid[i][j];
}
}
return dp[m-1][n-1];
}
最大子数组和
int maxSubArray(vector<int>& nums){
if(nums.empty()) return 0;
int len=nums.size();
int sum=0,maxnum=nums[0];
for(int i=0;i<len;i++){
sum+=nums[i];
maxnum=max(maxnum,sum);
sum=max(sum,0);
}
return maxnum;
}
最大子数组乘积
int maxProduct(vector<int>& nums) {
if (nums.empty()) return 0;
int maxEndHere=nums[0],minEndHere=nums[0];
int maxSoFar = nums[0];
for (int i=1; i<nums.size(); i++) {
if (nums[i]<0) swap(maxEndHere,minEndHere);
maxEndHere=max(maxEndHere*nums[i], nums[i]);
minEndHere=min(minEndHere*nums[i], nums[i]);
maxSoFar = max(maxEndHere, maxSoFar);
}
return maxSoFar;
}
Maximal Square
int maximalSquare(vector<vector<char>>& matrix){
int m = matrix.size();
if (!m) return 0;
int n = matrix[0].size();
vector<vector<int> > size(m, vector<int>(n, 0));
int maxsize = 0;
for (int j = 0; j < n; j++) {
size[0][j] = matrix[0][j] - '0';
maxsize = max(maxsize, size[0][j]);
}
for (int i = 1; i < m; i++) {
size[i][0] = matrix[i][0] - '0';
maxsize = max(maxsize, size[i][0]);
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == '1') {
size[i][j] = min(size[i-1][j-1], min(size[i-1][j], size[i][j-1]))+1;
maxsize = max(maxsize, size[i][j]);
}
}
}
return maxsize * maxsize;
}
Best Time to Buy and Sell Stock
Best Time to Buy and Sell StockI
int maxProfit(vector<int>& prices){
if(prices.size()<=1) return 0;
int lprice=prices[0];
int profit=0;
for(int i=0;i<prices.size();i++){
profit=max(prices[i]-lprice,profit);
lprice=min(prices[i],profit);
}
return profit;
}
Best Time to Buy and Sell StockII
int maxProfit(vector<int>& prices) {
int len=prices.size();
int temp=0;
for(int i=1;i<len;i++){
if(prices[i]>prices[i-1])
temp+=prices[i]-prices[i-1];
}
return temp;
}
Best Time to Buy and Sell StockIV
int maxProfit(int k, vector<int>& prices){
int n=prices.size();
if (n<=1) return 0;
if (k>=n/2) {
int maxPro = 0;
for (int i=1; i<n; i++) {
if (prices[i]>prices[i-1])
maxPro+=prices[i]-prices[i-1];
}
return maxPro;
}
vector<vector<int>> dp(k+1,vector<int>(n,0));
for (int i=1; i<=k; i++) {
int localMax=dp[i-1][0]-prices[0];
for (int j=1; j<n; j++) {
dp[i][j]=max(dp[i][j-1], prices[j]+localMax);
localMax=max(localMax, dp[i-1][j]-prices[j]);
}
}
return dp[k][n-1];
}