动态规划dp{0-1背包问题,最长公共子序列,最大子段和}

任务一 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;

}

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值