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