一、 01背包问题
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int m, n;
while(cin >> m >> n){
vector<int> w(n+1, 0);//每个物品的体积
vector<int> v(n+1, 0);//每个物品的价值
for(int i = 1; i <= n; i++)
cin >> w[i];
for(int i = 1; i <= n; i++)
cin >> v[i];
vector<vector<int>> vec(n+1, vector<int>(m+1, 0));//价值二维数组
for(int i = 1; i <= n; i++){//n是数量
for(int j = 1; j <= m; j++){//m是体积
if(w[i] > j)
vec[i][j] = vec[i-1][j];
else
vec[i][j] = max(vec[i-1][j], vec[i-1][j-w[i]] + v[i]);
}
}
cout << vec[n][m] << endl;
}
return 0;
}
二、最长公共子序列lcs
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s1, s2;
cin >> s1 >> s2;
int len1 = s1.length();
int len2 = s2.length();
int c[len1+1][len2+1];
for(int i = 0; i <= len1; i++){
for(int j = 0; j <= len2; j++){
if(i == 0 || j == 0)
c[i][j] = 0;
else if(s1[i-1] == s2[j-1])
c[i][j] = c[i-1][j-1] + 1;
else
c[i][j] = max(c[i-1][j], c[i][j-1]);
}
}
cout << c[len1][len2] << endl;
return 0;
}
三、最长公共子串
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s1, s2;
cin >> s1 >> s2;
int len1 = s1.length();
int len2 = s2.length();
int c[len1+1][len2+1];
int result = 0;
for(int i = 0; i <= len1; i++){
for(int j = 0; j <= len2; j++){
if(i ==0 || j == 0)
c[i][j] = 0;
else if(s1[i-1] == s2[j-1]){
c[i][j] = c[i-1][j-1] + 1;
result = max(c[i][j], result);
}
else
c[i][j] = 0;
}
}
cout<< result <<endl;
return 0;
}
四、最长上升子序列
#include <iostream>
#include <algorithm>
using namespace std;
int a[1005];
int res[1005];
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
res[i] = 1;
}
for(int i = 1; i < n; i++){
for(int j = 0; j < i; j++){
if(a[j] < a[i])
res[i] = max(res[i], res[j] + 1);
}
}
cout << *max_element(res, res + n) << endl;
return 0;
}
五、拿糖果
问题描述
妈妈给小B买了N块糖果,但他不允许小B直接吃掉。
假设当前有M块糖,小B每次可以拿p块糖,其中P是M的一个不大于根号下M的质因数。这时,妈妈就会在小B拿了P块糖以后再从糖堆里拿走P块糖。然后小B就可以接着拿糖
现在小B希望知道最多可以拿走多少糖。
解题思路
首先创建一个满足不大于根号下最大值MAXN的素数表,然后对素数表里的数逐个遍历
构建一个dp[i]数组,表示当糖果数量为i的时候所能拿的最多的糖果数量
对于dp[i] 的值:因为小B只能每次拿不大于根号下i的质因数,遍历素数表中满足条件的素数(prime[j] <= sqrt(i) && i % prime[j] == 0),更新dp[i]的值为(dp[i - 2 * prime[j]] + prime[j] )的最大值。
即: dp[i] = max(dp[i], dp[i - 2 * prime[j]] + prime[j]
这里的d[j - 2 * prime[j]] + prime[j] 表示拿走了prime[j] 块
代码
#include <iostream>
#include <math.h>
using namespace std;
int prime[50000];
int dp[100005];
int book[100005];
int cnt = 0;
void create() {
int len = sqrt(100005);
for(int i = 2; i <= len; i++) {
if(book[i] == 0){
prime[i] == i;
for(int j = i * i; j <= len; j = j + i) {
book[j] = 1;
}
}
}
}
int main() {
create();
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 0; j < cnt; j++) {
if(prime[j] > sqrt(i))
break;
if(i % prime[j] == 0) {
int temp1 = dp[i]; //若不拿 prime[j]块
int temp2 = dp[i - 2 * prime[j]] + prime[j]; //若拿 prime[j]块
dp[i] = temp2 > temp1 ? temp2 : temp1;
}
}
}
cout << dp[n];
return 0;
}