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;

int type[4] = {2,3,5,10};
int dp[1000]={0};
int  getMin(int sum)
{
    
    for (int i =1; i<=sum; i++)
    {
        if (i%type[0] ==0)
        {
            dp[i] = i/type[0];
        }
        else
            dp[i] = 65535;
    }
    for (int i =1; i <4; i++)
    {
        for (int j =type[i]; j <=sum; j++)
        {
            if (dp[j - type[i]] != 65535)
            {
                 dp[j] = min(dp[j],dp[j - type[i]] + 1);
            }
        }
    }
  
    if(dp[sum] == 65535)
    return -1;
    else
        return dp[sum];
}
int coinChange( int aim)
{
    int len = 4;
    vector<vector<int>> dp(len, vector<int>(aim+1,0));
    for(int i=1; i<=aim; i++)   //边界条件
    {
        dp[0][i] = INT_MAX;//
        if (i %type[0] == 0)
        {
            dp[0][i] = i/type[0];
        }
    }
    for(int i=1; i<len; i++)
    {
        for(int j=1; j<=aim; j++)
        {
            int leftup = INT_MAX;
            if( j>=type[i] && dp[i][j-type[i]] != INT_MAX )
            {
                leftup=dp[i][j-type[i]]+1;
            }
            dp[i][j] = min( dp[i-1][j], leftup );
        }
    }

    return dp[len-1][aim]==INT_MAX ? -1 : dp[len-1][aim];
}
int main()
{
    int n =0;
    while (cin >> n)
    {
        if(getMin(n) == coinChange(n))
            cout << getMin(n)<<" " << "good" <<endl;
        else
            cout <<"error"<<endl;
    }

}

(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];
}

猜你喜欢

转载自blog.csdn.net/weixin_39804483/article/details/88902138
今日推荐