1、动态规划专题

(1)将数组分成值相等两部分 

#include<iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;

//递归
int final = 0;
bool b = false;
bool f(vector<int> v, int i,int fool,int sum)
{
	if ( i== v.size())
	{
		return false;
	}
	if (fool ==1)
	{
		sum += v[i];
	}
	//sum += v[i]
	if (sum == final)
	{
		b = true;
		return true;
	}
	
	f(v, i + 1, 0, sum);
	f(v, i + 1, 1, sum);

}
bool func(vector<int> v)
{
	int sum = 0;
	for (int i =0 ; i < v.size(); i++)
	{
		sum +=v[i];
	}
	if (sum %2 ==1)
	{
		return false;
	}
	const int all = sum / 2;//背包总重量
	const int  inum = v.size();
	vector<vector<int>> dp(inum + 1,vector<int>(all+1,0));
	for (int i =1; i <=inum; i++)
	{
		for (int j =1; j <= all; j++)
		{
	//		cout << v[i - 1];
			if (j < v[i-1])//包里装不下这个物品
			{
				dp[i][j] = dp[i - 1][j];
			}
			else
			{
				//包里可以装下这个物品
				dp[i][j] = max(dp[i - 1][j],dp[i -1][j - v[i - 1]] + v[i - 1]);
			}
		}
	}
	
	if (dp[inum][all] ==all )
	{
		return true;
	}
	return false;
}

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(5);
	v.push_back(5);
	int sum = 0;
	final = 7;
	f(v, -1, 0, sum);
	cout << b << endl;

	cout << func(v)<<endl;
	system("pause");
	return 0;
}

(2)堆积木问题

#include <iostream>
#include <limits.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

// every block has 3 choice

struct block
{
    block(int x, int y, int z)
    {
        this->x = x;
        this->y = y;
        this->z = z;
        
    }
    int x, y, z;
};

bool comp(const block& a, const block& b) //
{
    if (a.x == b.x)//
        return a.y > b.y;
    return a.x > b.x;
}

int T, ans;
//int index;
int DP[200];//记录最大高度

void DP_TR(vector<block> BK)//构造DP表
{
   int index =4;
    int i, j;
    for (i = 0; i <index; ++i)
    {
        DP[i] = BK[i].z;
        for (j = 0; j < i; ++j)
        {
            if (BK[i].x < BK[j].x && BK[i].y < BK[j].y)//如果j号块比i号块的截面大,则将i号放在j号上面,更新高度
                DP[i] = max(DP[i], DP[j] + BK[i].z);
        }
    }
    cout << DP[index - 1] << endl;
}
int main()
{
   
    
    return 0;
}

 (3)走台阶问题

int recur(int n)
{
    if(n == 1)
        return 1;
    if (n == 2)
    {
        return 2;
    }
    return recur(n - 1) + recur(n - 2);
}
int getCount(int n)
{
    int sum =0;
    if (n == 1)
    {
        return 1;
    }
    if (n == 2)
    {
        return 2;
    }
    int a = 1;
    int b=  2;
    for (int i = 3; i <=n; i++)
    {
        sum  = a +b;
        a = b;
        b =sum;
    }
    return sum;
}

(4)硬币找零问题--(最少需要的硬币数量)

#include<iostream>
#include<string>
#include<vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    ;
    /**
     * @param coins: a list of integer
     * @param amount: a total amount of money amount
     * @return: the fewest number of coins that you need to make up
     */
    int coinChange(vector<int> &coins, int amount) {
        // write your code here
        sort(coins.begin(), coins.end());//排序是必要的 为了后面处理1
        int *dp = new int[amount +1];
        fill(dp,dp+amount + 1, 0);//初始化
        if ( amount <= 0) {
            return 0;//如果钱数小于0 一定是0种方法
        }
        if(coins.size() == 0)//如果数组长度是0,对于钱数大于0的值来说,一定没有
            return -1;
        for (int i =0; i<=amount; i++)//
        {
            if(coins[0] != 0)//
            {
                if (i%coins[0] ==0)
                {
                    dp[i] = i/coins[0];
                }
                else
                    dp[i] = INT_MAX;
            }
            else
            {
                if(coins.size() >1)
                {
                    if (i%coins[1] ==0)
                    {
                        dp[i] = i/coins[1];
                    }
                    else
                        dp[i] = INT_MAX;
                }
                else
                    return -1;
            }
        }
        for (int i =1; i <coins.size(); i++)
        {
            for (int j =coins[i]; j <=amount; j++)
            {
                if (dp[j - coins[i]] != INT_MAX)
                {
                    dp[j] = min(dp[j],dp[j - coins[i]] + 1);
                }
            }
        }
        
        if(dp[amount] == INT_MAX)
            return -1;
        else
            return dp[amount];
        
    }
};

(5)挖矿问题

#include<iostream>
#include <algorithm>
using namespace std;

const int W = 10;
const int number = 5;
const int VALUE[] = { 500, 200, 300, 350, 400 };
const int WEIGHT[] = { 5, 3, 4, 3, 5 };


//function Make( i {处理到第i件物品} , j{剩余的空间为j}) :integer;
int Make(int i, int j)
{
	int r = 0;
	if (i == -1)
	{
		return 0;
	}
	if (j >= WEIGHT[i])   //背包剩余空间可以放下物品 i  
	{
		r =   max(Make(i - 1, j - WEIGHT[i]) + VALUE[i], Make(i - 1, j));
	}
	return r;
	
}
int getGold(int n, int w)
{
	int pr[1000];
	for (int i =0 ; i <= n; i++)
	{
		if (i < WEIGHT[0])//背包重量
		{
			pr[i] = 0;
		}
		else
			pr[i] = VALUE[0];
	}
	for (int i =1; i <= n; i++)
	{
		for (int j =W ; j >=WEIGHT[i]; j--)//背包重量
		{
				pr[j] = max(pr[j], pr[j - WEIGHT[i]] + VALUE[i]);
		}
	}
	return pr[w];
}
void main()
{
	int maxValue = Make(number - 1, W);
	cout << "maxValue: " << maxValue << endl;
	cout << getGold(5,10);
	system("pause");
}

(6)硬币找零

#include <iostream>

using namespace std;
long long dp[10001] = {1};//特别注意
const int w[] = { 1, 5, 10, 25, 50 };
int getCount()
{
     for (int i = 0; i < 5; i++)
        for (int j = w[i]; j <= 10000; j++)
            dp[j] += dp[j - w[i]];//不用这个硬币 用这个硬币
    int money =0;
    while(cin>> money)
    cout  << dp[money]<<endl;
return 0;
}
//方法二用二维数组来做
int dps[5][10001] ={1}; 
int getCount_()
{
    int money =0;
    for(int i =0; i <5; i++)
        dps[i][0] = 1;
  for(int i =0 ; i< 5; i++)
  {
      for(int j =w[i]; j <= 10000; j++)
      {
          dps[i][j] = dps[i][j] + dps[i][j -w[i]];
       }
  }
   while(cin>> money)
    cout  << dps[4][money]<<endl;
return 0;
}
int main()
{
    getCount();
    return 0;
}

修改版本

//
//  main.cpp
//  dprogram
//
//  Created by 吴珝君 on 2019/4/2.
//  Copyright © 2019年 闲着也是贤者. All rights reserved.
//

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
 (1)从台阶问题的例子出发
 有一座n级台阶,从下往上走,每跨一步向上1级或者2级台阶。请求出一共有多少种走法。
 思路: 假如有10级台阶,则0-9级的走法数量+ 0-8级的走法数量
 */
int type[5] = {1,5,10,25,50};
int dp[1000]={0};
int  getCount(int sum)
{
    
    for (int i =0; i<=sum; i++)
    {
        if (i%type[0] ==0)
        {
            dp[i] = 1;
        }
        else
            dp[i] = 0;
    }
    for (int i =1; i <5; i++)
    {
        for (int j =type[i]; j <=sum; j++)
        {
            if (dp[j - type[i]] != 65535)
            {
                dp[j] = dp[j]+dp[j - type[i]];
            }
        }
    }
    
    if(dp[sum] == 65535)
        return -1;
    else
        return dp[sum];
}

    int main(int argc, const char * argv[])
    {
    // insert code here...

        cout << getCount(11)<<endl;
    return 0;
}

(7)硬币问题:一个硬币只使用一次

int  getCount_(int sum)
{
    
    for (int i =0; i<=sum; i++)
    {
        if (i == type[0])
        {
            dp[i] = 1;
        }
        else
            dp[i] = 0;
    }
    for (int i =1; i <5; i++)
    {
       for (int j = sum; j >=type[i]; j--)//之所以要反着来是因为其依赖得是上一行的值。如果不反着来的话,相当于我先将当前值修改了给后面的值用,这样就变成了依赖于当前行,矛盾,因而要反过来。
        {
            if (dp[j - type[i]] != 65535)
            {
                dp[j] = dp[j]+dp[j - type[i]];
            }
        }
    }
    
    if(dp[sum] == 65535)
        return -1;
    else
        return dp[sum];
}

(8)0-1背包问题

int weight[5] = {2,2,4,6,3};
int value[5] ={3,4,8,9,6};
int  getMin(int all)
{
    int res[5][100] ={0};//保存所有状态
    //边界条件
    for(int i =0 ; i <= all; i++)
    {
        if (i <weight[0])
        {
            res[0][i] = 0;
        }
        else
            res[0][i] = value[0];
    }//最多一个物品能够达到的装袋
    for (int i = 1; i < 5; i++)
    {
        for (int j = 0; j <= all; j++)
        {
            if ( j < weight[i])
            {
                res[i][j] = res[i -1][j];
            }
            else
            {
                res[i][j] = max(res[i -1][j] , res[i -1][j - weight[i]] + value[i] );
            }
        }
        
      
    }
    
    int j = all;
    for (int i = 4; i>=1; i--)
    {
        if (j - weight[i]>=0 && res[i -1][j - weight[i]] >0)
        {
            cout <<"---->" << weight[i];
            j = j - weight[i];
        }
    }
    if(j != 0)
    {
        cout <<"----->" <<weight[0] << endl;
    }
   
  return res[4][all];
    
}

(9)杨辉三角

//杨辉三角
int triangle(vector<vector<int>> v)
{
    for (int i = 3; i >=0 ; i--)
    {
        for (int j =0; j <= i; j++)
        {
            v[i][j] = v[i][j] + min(v[i+1][j],v[i + 1][j+1]) ;
            cout <<" i " << i << "j "<<j <<" " << v[i][j] << endl;
        }
    }
    
    cout << v[0][0]<< endl;
    return 0;
}

(10)最长公共子序列

//dp问题
int  getmax(vector<int> arr)
{
    
    int *longest = new int[arr.size()];
    fill(longest,longest+arr.size() , 0);
    int len =arr.size();
    for (int i=0; i<len; i++)
        longest[i] = 1;
    
    for (int j=1; j<len; j++)//所有需要匹配的子串
    {
        for (int i=0; i<j; i++)//已经匹配的元素
        {
            //j是待比较的元素 i是已经获得的子序列中的最后一个元素 如果比最后一个元素还大  说明这个也是递增的
            if (arr[j]>arr[i] && longest[j]<longest[i] +1)//
            { //注意longest[j]<longest[i]+1这个条件
                longest[j] = longest[i] + 1; //计算以arr[j]结尾的序列的最长递增子序列长度
            }
            
        }
    }
    
    sort(longest, longest + arr.size());
    return longest[arr.size() - 1];
}

(8)最短编辑距离与最长递增子序列

#include<iostream>
#include<string>
#include<vector>
#include <algorithm>
using namespace  std;
int getMax(vector<int> can, vector<int> child)
{
	sort(can.begin(), can.end());
	sort(child.begin(), child.end());
	int count = 0;
	int j = 0;
	for (int i = 0; i < child.size(); i++)
	{
		while (j < can.size())
		{
			if (child[i] <= can[j])
			{
				count++;
				j++;
				break;
			}
			j++;
		}
	}
	return count;
}

int dp[100] = { 1 };
//从左向右扫描,找出连续的非严格递增串,删除最后一个
int LIS(vector<int> str)
{
	if (str.empty()){
		return 0;
	}
	for (int i = 0; i < str.size(); i++)
	{
		for (int  j = i +1; j < str.size(); j++)
		{
			if (str[i] < str[j])
			{
				dp[j] = max(dp[j], dp[i] +1);
			}
		}
	}

	int m = 0;
	for (int i = 0; i < str.size(); i++)
	{
		if (m < dp[i])
		{
			m = dp[i];
		}
	}
	return m;
		
}
long long total[1000];
int main()
{
	vector<int> v;
	srand(NULL);
	for (int i = 0; i < 20; i++)
	{
		int T =rand() % 10;
		cout << T << " ";
		v.push_back(T);

	}
	cout << endl;
	cout << LIS(v);


	
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值