/**
动态规划(设计动态规划算法以解决问题)
动态规划题目的代码量都不大
leetcode 198. 打家劫舍
写出动态规划方程,迭代方程如下
(1)初始条件
dp[0]=nums[0]
dp[1]=max(nums[0],nums[1])
(2)迭代公式
dp[i]=max(dp[i-1],nums[i]+dp[i-2])
**/
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0){
return 0;
}
if(nums.size()==1){
return nums[0];
}
vector<int> dp;
dp.push_back(nums[0]);
dp.push_back(max(nums[0],nums[1]));
for(int i=2;i<nums.size();i++){
dp.push_back(max(dp[i-1],dp[i-2]+nums[i]));
}
return dp[dp.size()-1];
}
};
int main(){
int a[5]={2,7,9,3,1};
vector<int> nums;
for(int i=0;i<5;i++){
nums.push_back(a[i]);
}
Solution s;
cout<<s.rob(nums)<<endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
/**
leetcode 53. 最大子序和
如果将dp数组定义成从第0个字符到i个字符构成的字符串中
的最大自序和,则dp[i+1]和dp[i]之间的关系并不连续
故而在这里将dp[i]定义成从第0个字符到第i个字符构成的字符串
中最大子序和,且该子序列最后一个字符必须是字符串的第i个字符
则dp数组中的最大值即为返回值(而并不是最后一个数值)
**/
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0){
return 0;
}
if(nums.size()==1){
return nums[0];
}
vector<int> dp;
dp.push_back(nums[0]);
int max_value=nums[0];
for(int i=1;i<nums.size();i++){
if(dp[i-1]>0){
dp.push_back(dp[i-1]+nums[i]);
if(dp[i-1]+nums[i]>max_value){
max_value=dp[i-1]+nums[i];
}
}
else{
dp.push_back(nums[i]);
if(nums[i]>max_value){
max_value=nums[i];
}
}
}
return max_value;
}
};
int main(){
int a[9]={-2,1,-3,4,-1,2,1,-5,4};
vector<int> nums;
for(int i=0;i<9;i++){
nums.push_back(a[i]);
}
Solution s;
cout<<s.maxSubArray(nums)<<endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
/**
leetcode 322. 零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount
编写一个函数来计算可以凑成总金额所需的最少的硬币个数
如果没有任何一种硬币组合能组成总金额,返回 -1
算法:
dp[i]数组表示总金额数为i时,所需要的钞票最少张数
dp[0] 无意义
写出dp[N] 数组的递推公式即可
**/
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if(amount==0){
return 0;
}
int dp[amount+1]={-1};
for(int i=0;i<coins.size();i++){
if(coins[i]<amount){
// 大于当前数值的硬币并不会被用
dp[coins[i]]=1;
}
if(coins[i]==amount){
return 1;
}
}
for(int j=1;j<amount+1;j++){
if(dp[j]==1){
continue;
}
else{
int min_count=0x7fffffff;
// C++中的int整型是4个字节,共32个bit位
bool visible=false;
for(int k=0;k<coins.size();k++){
if(coins[k]>j){
continue;
}
if(dp[j-coins[k]]>0 and dp[j-coins[k]]+1<min_count){
min_count=dp[j-coins[k]]+1;
visible=true;
}
}
if(visible){
dp[j]=min_count;
}
else{
dp[j]=-1;
}
}
}
return dp[amount];
}
};
int main(){
int a[8]={27,398,90,323,454,413,70,315};
vector<int> nums;
for(int i=0;i<8;i++){
nums.push_back(a[i]);
}
// vector<int> nums;
// nums.push_back(1);
Solution s;
cout<<s.coinChange(nums,6131)<<endl;
return 0;
}
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/**
leetcode 120. 三角形最小路径和
**/
class Solution {
public:
int minimumTotal(vector<vector<int> >& triangle) {
if(triangle.size()==0){
return 0;
}
if(triangle.size()==1){
return triangle[0][0];
}
vector<vector<int> > result;
vector<int> line1;
line1.push_back(triangle[0][0]);
result.push_back(line1);
vector<int> line2;
line2.push_back(triangle[0][0]+triangle[1][0]);
line2.push_back(triangle[0][0]+triangle[1][1]);
result.push_back(line2);
vector<int> temp_line;
for(int i=2;i<triangle.size();i++){
temp_line.clear();
temp_line.push_back(result[i-1][0]+triangle[i][0]);
for(int j=1;j<triangle[i].size()-1;j++){
temp_line.push_back(triangle[i][j]+min(result[i-1][j-1],result[i-1][j]));
}
temp_line.push_back(result[i-1][i-1]+triangle[i][i]);
result.push_back(temp_line);
}
// for(int m=0;m<result.size();m++){
// for(int n=0;n<result[m].size();n++){
// cout<<result[m][n]<<",";
// }
// cout<<endl;
// }
//
// cout<<"during debug "<<endl;
return *min_element(result[result.size()-1].begin(),result[result.size()-1].end());
}
};
int main(){
vector<int> line0;
line0.push_back(2);
vector<int> line1;
line1.push_back(3);
line1.push_back(4);
vector<int> line2;
line2.push_back(6);
line2.push_back(5);
line2.push_back(7);
vector<int> line3;
line3.push_back(4);
line3.push_back(1);
line3.push_back(8);
line3.push_back(3);
vector<vector<int> > triangle;
triangle.push_back(line0);
triangle.push_back(line1);
triangle.push_back(line2);
triangle.push_back(line3);
Solution s;
cout<<s.minimumTotal(triangle)<<endl;
return 0;
}
#include<vector>
#include<iostream>
using namespace std;
/**
leetcode 64. 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,
使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
**/
class Solution {
public:
int minPathSum(vector<vector<int> >& grid) {
// 将二维矩阵第一行和第一列的数字进行初始化
// 从起始点到达第一行或者第一列的点的路径是唯一的
int m=grid.size();
int n=grid[0].size();
for(int i=1;i<n;i++){
grid[0][i]+=grid[0][i-1];
}
for(int j=1;j<m;j++){
grid[j][0]+=grid[j-1][0];
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
grid[i][j]+=min(grid[i][j-1],grid[i-1][j]);
}
}
return grid[m-1][n-1];
}
};
int main(){
vector<vector<int> > grid;
vector<int> line1;
int a[3]={1,3,1};
for(int i=0;i<3;i++){
line1.push_back(a[i]);
}
grid.push_back(line1);
a[1]=5;
line1.clear();
for(int i=0;i<3;i++){
line1.push_back(a[i]);
}
grid.push_back(line1);
a[0]=4;
a[1]=2;
line1.clear();
for(int i=0;i<3;i++){
line1.push_back(a[i]);
}
grid.push_back(line1);
Solution s;
cout<<s.minPathSum(grid)<<endl;
return 0;
}