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