您的位置:首页 > 其它

【动态规划基础篇】【矩阵取数/最大字段和/最长公共子序列(LCS)/编辑距离/最长上升子序列(LIS)】

2016-05-22 13:47 549 查看

矩阵取数问题

题目链接:http://www.51nod.com/tutorial/course.html#!courseId=1


题目描述

一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值。


输入

第1行:N,N为矩阵的大小。(2 <= N <= 500)

第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值。(1 <= N[i] <= 10000)


输出

输出能够获得的最大价值。


输入示例

3

1 3 3

2 1 3

2 2 1

输出示例

11

AC代码:

//  dp矩阵取数问题;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int a[505][505];
int dp[505][505];   //  到x,y点的最大奖励;
int n;
cin.sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
memset(dp,0,sizeof(dp));
dp[0][0]=a[0][0];
for(int i=1;i<n;i++)
dp[0][i]=dp[0][i-1]+a[0][i];
for(int i=1;i<n;i++)
dp[i][0]=dp[i-1][0]+a[i][0];
for(int i=1;i<n;i++){
for(int j=1;j<n;j++){
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
}
}
cout<<dp[n-1][n-1]<<endl;
return 0;
}


最大子段和问题

题目链接:http://www.51nod.com/tutorial/course.html#!courseId=2

题目描述

输入
N个整数组成的序列a[1],a[2],a[3],…,a
,求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值。当所给的整数均为负数时和为0


输入

第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)



输出

输出最大子段和。



输入示例

6
-2
11
-4
13
-5
-2


输出示例

20


AC代码:

//  最大子段和

#include<iostream>

#include<cstring>

#define LL long long

using namespace std;

int main()

{

    int n;

    int a[51010];

    cin.sync_with_stdio(false);

    cin>>n;

    for(int i=0;i<n;i++)

        cin>>a[i];

    LL maxSum=0;

    LL ans=0;

    int s=0,ss=0,ee=0;    //  分别表示起始和终止位置;

    for(int i=0;i<n;i++){

        if(maxSum>0){   //  大于,就可以一直加;

            maxSum+=a[i];

        }else{

            s=i;            //  标记起始位置

            maxSum=a[i];    //  重新开始;

        }

        if(maxSum>ans){     //  判断是否能够更新ans;

            ans=maxSum;

            ss=s;

            ee=i;

        }

    }

    //cout<<ss<<' '<<ee<<endl;  //分别记录起始位置和终止位置;

    cout<<ans<<endl;

    return 0;

}

最长公共子序列问题

题目链接:http://www.51nod.com/tutorial/course.html#!courseId=4


题目描述

给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。



输入

第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)



输出

输出最长的子序列,如果有多个,随意输出1个。



输入示例

abcicba
abdkscab


输出示例

abca



AC代码:

//最长公共子序列
//记录序列;
#include<iostream>
using namespace std;
int dp[1010][1010]={0};
int s[1010][1010]={0};       //  记录结果;
string s1,s2;
void print(int i,int j)
{
if(i==0||j==0) return;
if(s[i][j]==0){     //  相同情况;
print(i-1,j-1);
cout<<s1[i];
}
else if(s[i][j]==1)
print(i-1,j);
else
print(i,j-1);
}
int main()
{
cin.sync_with_stdio(false);
cin>>s1>>s2;
s1="#"+s1;
s2="@"+s2;
int len1=s1.size();
int len2=s2.size();
for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
if(i==0||j==0){
dp[i][j]=0;
s[i][j]=0;
}else{
if(s1[i]==s2[j]){
dp[i][j]=dp[i-1][j-1]+1;
s[i][j]=0;
}else{
if(dp[i-1][j]>=dp[i][j-1]){
dp[i][j]=dp[i-1][j];
s[i][j]=1;
}else{
dp[i][j]=dp[i][j-1];
s[i][j]=-1;
}
}
}
}
}
print(len1-1,len2-1);
//cout<<dp[len1-1][len2-1]<<endl;
//cout<<s[len1-1][len2-1]<<endl;
return 0;
}

编辑距离问题

题目链接:http://www.51nod.com/tutorial/course.html#!courseId=3

题目描述

编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如将kitten一字转成sitting:

sitten (k->s)

sittin (e->i)

sitting (->g)

所以kitten和sitting的编辑距离是3。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。

给出两个字符串a,b,求a和b的编辑距离。

输入

第1行:字符串a(a的长度 <= 1000)。
第2行:字符串b(b的长度 <= 1000)。


输出

输出a和b的编辑距离


输入示例

kitten
sitting


输出示例

3


AC代码:

//  编辑距离;
#include<iostream>
#include<cstring>
using namespace std;
int len1,len2;
string s1,s2;
int dp[1005][1005];
void init()
{
s1="#"+s1;
s2="@"+s2;
len1=s1.size();
len2=s2.size();
for(int i=0;i<len1;i++)
dp[i][0]=i;
for(int i=0;i<len2;i++)
dp[0][i]=i;
}
int main()
{
cin.sync_with_stdio(false);
cin>>s1>>s2;
init();
for(int i=1;i<len1;i++){
for(int j=1;j<len2;j++){
dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+((s1[i]==s2[j])?0:1));
//cout<<dp[i][j]<<endl;
}
}
cout<<dp[len1-1][len2-1]<<endl;
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: