任务一 0-1背包问题
算法描述
1.设f[i][j]为装入第i个物品时,背包剩余容量为j。w[i]为第i个物品重量,v[i]为第i个物品价值
2.采用递推公式:
当 j<wi f[i][j]=f[i+1][j];否则 f[i][j]=max{f[i+1][j-w[i]]+v[i], f[i+1][j]}
由下至上推出剩余第1个物品时,背包的最大价值;
3.利用f[i][j]数组及递推规律 若f[i][j] = f[i+1][j-w[i]] +v[i], 此物品装入背包,否则不然。由上至下推出装入背包的物品。
源代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
int c;
int w[10]={0};
int v[10]={0};
int i = 1;
cin >> n >> c;
while(i <= n){
cin >> w[i++];
}
i = 1;
while(i <= n){
cin >> v[i++];
}
int f[10][100]={0};
for(i = n; i > 0; i--){
for(int j = 1; j <= c; j++){
if( w[i] > j )
f[i][j] = f[i+1][j];
else{
f[i][j] = ((f[i+1][j-w[i]]) + v[i]) > f[i+1][j]?(f[i+1][j-w[i]] + v[i]):f[i+1][j];
}
}
}
/* for( i = 1; i <= n + 1; i++){
for(int j = 1; j <= c; j++){
cout << f[i][j] << " ";
}
cout << endl;
}*/
i = 1;
int j = c;
while(j > 0 && i <= n){
if(f[i][j] == f[i+1][j - w[i]] + v[i]) {
cout << i << " " ;
j -= w[i];
}
i++;
}
cout << endl;
cout << f[1][c] << endl;
}
任务二:最长公共子序列
算法描述
1.f[i][j]为字符串a的前i+1(字符数组下标从0开始)的字符和字符串b前j+1个字符的最大公共子序列的长度;c[i][j]用于标记f[i][j]变化
2.利用递推公式 :
若i= -1 | | j= -1, f[i][j] = 0 , c[i][j] = 0 ;
若a[i] = b[j], f[i+1][j+1] = f[i][j] + 1 , c[i][j] = 1;
若 a[i] != b[j], f[i+1][j+1] = max{f[i][j+1], f[i+1][j]} ; 若f[i][j+1] > f[i+1][j] c[i][j]=2 否则 c[i][j] = 3;
求出当i = a.size , j = b.size() 时 f[i][j]的取值即为a b的最大公共子序列的长度。
3.利用数组c[i][j]及递归公式求出最大公共子序列
若i == 0 || j == 0; 结束递归
若 c[i][j] == 1 输出a[i-1] , i --, j --;
若 c[i][j] == 2 , i--;
若 c[i][j] == 3 , j –;
源代码
#include<bits/stdc++.h>
using namespace std;
void LCS(int i , int j , string a, int b[][100]){
if(i == 0 || j == 0)
return ;
if(b[i][j] == 1){
LCS(i-1, j-1, a, b);
cout << a[i-1];
}
else if(b[i][j] == 2){
LCS(i-1, j, a, b);
}
else{
LCS(i, j-1, a, b);
}
}
int main(){
string a;
string b;
cin >> a >> b;
int f[100][100]={0};
int c[100][100]={0};
int n = a.size();
int m = b.size();
for(int i = -1; i < n; i++){
for(int j = -1; j < m; j++){
if(i == -1 || j == -1){
f[i+1][j+1] = 0;
}
else if(a[i] == b[j]){
f[i+1][j+1] = f[i][j] + 1;
c[i+1][j+1] = 1;
}
else {
if(f[i][j+1]>f[i+1][j]){
f[i+1][j+1] = f[i][j+1];
c[i+1][j+1] = 2;
}
else {
f[i+1][j+1] = f[i+1][j];
c[i+1][j+1] = 3;
}
}
}
}
LCS(n, m, a, c);
cout << endl;
}
任务三 最大子段和
算法描述
1.设sum为以当前元素结尾的最大子段和,max为当前子段最大子段和。
begin,end记录最大子段开始和结束位置
2.利用递推公式
若 sum <= 0, sum = a[i] ,begin = i
否则 sum =+a[i]
若 sum > max , max = sum , end = i
3.当i = a.size()时 max即为所求值。
源代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int a[100]={0};
int n;
int i = 0;
cin >> n;
while (i < n){
cin >> a[i++];
}
int begin = 0;
int end = 0;
i = 0;
int max = 0;
int sum = 0;
while(i < n){
if(sum <= 0) {
sum = a[i];
begin = i;
}
else
sum += a[i];
if(sum > max){
max = sum;
end = i;
}
i ++;
}
cout << max << " " << begin << " " << end << endl;
}