暑假专题2,DP入门

1、LCS(最长公共子序列)

B - Common Subsequence

subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, …, xm > another sequence Z = < z1, z2, …, zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, …, ik > of indices of X such that for all j = 1,2,…,k, x
ij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

Input
The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

Output
For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

Sample Input

abcfbc abfcab
programming contest
abcd mnp

Sample Output
4
2
0

#include<stdio.h>
#include<string.h>
int dp[1005][1005];
char a[1005],b[1005];
int ma(int a,int b,int c){
    int tem=a;
    if(b>=a)    tem=b;
    if(tem>=c)    return tem;
    else          return c;
}
int main(){
    while(scanf("%s %s",a,b)!=EOF){
        memset(dp,0,sizeof(dp));
        int l=strlen(a);
        int k=strlen(b);
        for(int i=1;i<=l;i++){
            for(int j=1;j<=k;j++){
                if(a[i-1]==b[j-1])      dp[i][j]=ma(dp[i-1][j-1]+1,dp[i][j-1],dp[i-1][j]);
                else                    dp[i][j]=ma(dp[i-1][j],dp[i][j-1],0);
            }
        }
        printf("%d\n",dp[l][k]);
    }
}

2、LIS(最长上升子序列)

f[i]=max(f[j]+1) {j=1、2、3……i-1}

3、数字三角形

7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

(Figure 1)
Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.

Input
Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output
Your program is to write to standard output. The highest sum is written as an integer.

Sample Input5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

#include <stdio.h>
#include <algorithm>
using namespace std;
int a[101][101];

int main(){
	int i,n,j,k;
	scanf("%d",&n);
	for( i = 0; i < n; i++ )
	for( j = 0; j <= i;j++ ){
		scanf("%d",&a[i][j]);
	}
	for( i--; i >= 0; i-- )
	for( j=0; j <= i; j++ ){
		a[i][j] += max(a[i+1][j],a[i+1][j+1]);
	}
	printf("%d\n",a[0][0]);
} 

4、01背包

从N个物品中选择一些物品进入背包,背包体积为V,每个物品都有其自身的价值和体积,要求不超过背包体积的情况下,价值最大。

int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        for(int i=0;i<n;i++)    scanf("%d %d",&w[i],&d[i]);
        memset(s,0,sizeof(s));
        for(int i=0;i<n;i++)
            for(int j=m;j>=w[i];j--)
                s[j]=ma(s[j],s[j-w[i]]+d[i]);
        ans=0;
        for(int i=1;i<=m;i++)   ans=ma(ans,s[i]);
        printf("%d\n",ans);
    }
    return 0;
}

5、完全背包

与01背包不同的是,01背包每个物品只能选择一次,而完全背包每个物品可以选择无数次,把01背包循环的逆序改成正序即可。

for(int i=0;i<n;i++)
            for(int j=w[i];j<=m];j++)
                s[j]=ma(s[j],s[j-w[i]]+d[i]);
 

6、多重背包

与01背包不同的是,每种物品可以选择限定的次数,用二进制拆分成01背包或者单调队列来做、

///拆分过程
scanf("%d %d",&num,&val);
            int i=1,cnt=0;
            while(num>=i){
                s[cnt++]=i*val;
                num-=i;
                i*=2;
            }
            s[cnt++]=num*val;

7、分组背包

与01背包不同的是,给你n组,第i组有ai个物品,要求你每组最多选一个,是背包的价值最大。

for(int i=1;i<=n;i++)//第i组
            for(int j=m;j>=0;j--)//背包容量
                for(int k=1;k<=c[i];k++)//第i组的所有物品
                //必须把k放在内层,不然不是分组背包
                    if(j>=k)
                        dp[j]=ma(dp[j],dp[j-k]+w[i][k]);

8、背包组合

四种背包的组合问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值