51nod 简单的动态规划

1006 最长公共子序列Lcs

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

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

比如两个串为:

abcicba

abdkscab

ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。

Input

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

Output

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

Input示例

abcicba
abdkscab

Output示例

abca状态转移方程为dp[i][j] = a[i]==a[j]?dp[i-1][j-1]+1:max(dp[i-1][j],dp[i][j-1]),然后用dfs搜索回去
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std;

char a[1005];
char b[1005];
int dp[1005][1005];
int pre[1005][1005];

void dfs(int m,int n)
{
    if(m==0||n==0)
        return;
    if(pre[m][n]==1)
    {
        dfs(m-1,n-1);
        cout<<a[m];
    }
    else if(pre[m][n]==2)
    {
        dfs(m-1,n);
    }
    else
    {
        dfs(m,n-1);
    }
}
int main()
{
    int i,j,len1,len2;
    //memset(dp,0,sizeof(dp));
    //memset(pre,0,sizeof(pre));

    cin>>a+1>>b+1;

    len1=strlen(a+1);
    len2=strlen(b+1);

    for(i=1;i<=len1;i++)
    {
        for(j=1;j<=len2;j++)
        {
            if(a[i]==b[j])
            {
                dp[i][j]=dp[i-1][j-1]+1;
                pre[i][j]=1;
            }
            else
            {
                if(dp[i-1][j]>dp[i][j-1])
                {
                    dp[i][j]=dp[i-1][j];
                    pre[i][j]=2;
                }
                else
                {
                    dp[i][j]=dp[i][j-1];
                    pre[i][j]=3;
                }
            }
        }
    }
    dfs(len1,len2);
    cout<<endl;
    return 0;
}

1134 最长递增子序列

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 取消关注

给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)

例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。

Input

第1行:1个数N,N为序列的长度(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)

Output

输出最长递增子序列的长度。

Input示例

8
5
1
6
8
2
4
5
10

Output示例

5

相关问题

最长递增子序列 V2

160

最长递增子序列的数量

160

思路1:

dp[i] = MAX(a[j]<a[i])__dp[j])+1 j是0到i内小于a[i]的j,dp[i]是他们最大值加一.但是这样由于每次都要遍历前面的数组导致超时,

思路二

在这里引入一个栈,不断向其中插入新的元素,最后取栈顶位置输出纪委最长递增子序列。

在插入时应当注意,如果插入元素大于栈顶元素,那么继续进栈,否则将元素插入到lower_bound搜索得到的不小于元素键值的下标处并覆盖原键值(这里对最优解不会有影响,因为求的只是长度)。

网上的代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 1E4 * 5 + 10;
int a[maxn],stk[maxn];
int main(){
        int n;
        scanf("%d",&n);
        for(int i = 1 ; i <= n ; ++i){
                scanf("%d",&a[i]);
        }
        int pcur = 0;
        for(int i = 1;i <= n;++i){
                if(!pcur){
                        stk[pcur++] = a[i];
                }else {
                        if(a[i] > stk[pcur - 1]){
                                stk[pcur++] = a[i];
                        }else if(a[i] < stk[pcur - 1]){
                                int pos = lower_bound(stk,stk + pcur,a[i]) - stk;
                                stk[pos] = a[i];
                        }
                }
        }
        printf("%d\n",pcur);
        return 0;
}

1085 背包问题

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。

Input

第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000)
第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)

Output

输出可以容纳的最大价值。

Input示例

3 6
2 5
3 8
4 9

Output示例

14

状态转移
dp[MAXN][10000] 表示前i个物品空间为v的价值
状态转移的方程有放和不放两种,可得:
dp[i][m] = max(dp[i-1][m]__不放,dp[i-1][m-w[i]]+v[i])

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN =101;
/*
状态转移
dp[MAXN][10000] 表示前i个物品空间为v的价值
状态转移的方程有放和不放两种,可得:
    dp[i][m] = max(dp[i-1][m]__不放,dp[i-1][m-w[i]]+v[i])
*/
int dp[MAXN][10001];
int w[MAXN],v[MAXN];
int main()
{
    int n,maxw,max_all=-1;
    scanf("%d%d",&n,&maxw);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&w[i],&v[i]);
        if(i==0)
        {
            dp[0][w[i]] = v[i];
        }
        else
        {
            for(int k=0;k<=maxw;k++)
            {
                if(k<w[i])
                    dp[i][k]=dp[i-1][k];//没有空间
                else
                    dp[i][k] = max(dp[i-1][k],dp[i-1][k-w[i]]+v[i]);
                max_all=max(max_all,dp[i][k]);
            }
        }
    }
    cout<<max_all<<endl;
    return 0;

1183 编辑距离

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

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

例如将kitten一字转成sitting:

sitten (k->s)

sittin (e->i)

sitting (->g)

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

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

Input

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

Output

输出a和b的编辑距离

Input示例

kitten
sitting

Output

3

在这里删除元素和插入的效果相同可以不用考虑,只考虑替换和插入dp[i][j]表示由a的前i个字符转换到b的前j个字符所需要的步数,插入是

dp[i][j] = max(dp[i-1][j],dp[i][j-1])+1,替换是,dp[i][j] = dp[i-1][j-1],当a[i]==b[j]  不必操作 dp[i][j]=dp[i-1][j-1]可得dp[i][j] = max(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+a[i]==b[j]?0:1)

时间: 2024-08-27 19:43:43

51nod 简单的动态规划的相关文章

一道简单的动态规划题目——House Robber

一.题目 House Robber(一道Leetcode上的关于动态规划的简单题目)具体描述如下: There is a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent hous

leadcode的Hot100系列--62. 不同路径--简单的动态规划

题目比较清晰,简单来说就是: A B C D E F G H I J K L 只能往右或者往下,从A到L,能有几种走法. 这里使用动态规划的方法来做一下. 动态规划最重要的就是动态方程,这里简单说下这个动态方程怎么做出来的吧. 记 f(B) 为 A到B总共可以有的走法. 想知道f(L),那其实只要知道f(H)和f(K)就可以了. 因为从A到H之后,再想到L就只有一种方法,AK同理,所以 f(L) = f(H) + f(K). 那f(H)呢,就等于 f(D)+f(G),这里就很容易得到他的动态方程

数塔 简单的 动态规划

挺简单的 , 从下向上将 下一行的 数字向上 一行 加     然后  将 这一行的  再向上 +   加到 最上面的时候 最上面的 就是 最大的值 #include<stdio.h> #include<algorithm> using namespace std; int a[101][101]; int max(int x,int y) { return x>y?x:y; } int main() { int i,j,n,t; scanf("%d",&

简单线性动态规划 —— 编辑距离

可用滚动数组压缩空间,略 if s[i] = t[j] then dp[i, j] := dp[i-1, j-1]          // no operation required else dp[i, j] := min( dp[i-1, j] + 1,     // a deletion dp[i, j-1] + 1,     // an insertion dp[i-1, j-1] + 1  // a substitution ) 加权的情况: dp[i][j] := min( dp[i

HDU 1176 免费馅饼 好像是简单的动态规划吧

题目链接~~http://acm.hdu.edu.cn/showproblem.php?pid=1176 刚开始数组越界,RT了两回     %>_<%   在坐标上要注意j-1时 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 #define max(a,b) (a

1112.拦截导弹(简单的动态规划)

题目描述: 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹.拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹. 输入: 每组输入有两行, 第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25), 第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的

hdu 1003 Max Sum 简单动态规划

很简单的动态规划但ac率低于四分之一了,状态转移方程: dp[i]=max(dp[i-1]+a[i],a[i]) 注意几点: case 之间有空格 输入的最小负数为-1000 有多组答案找出第一个的意思是,从头便利,得到第一个最大的和就输出被,然后break: /************************************************************************* > File Name: hdu1231.cpp > Author: yang >

HDU 1176 免费馅饼 简单动态规划

世道很简单的动态规划,但是却错了,让我很无语,改来改去还是不对,第二天有写就对了,之后我就耐着性子慢慢比较之前的错误代码,发现 第一次错:纯粹用了a[i][j]+=max3(a[i+1][j-1], a[i+1][j], a[i+1][j+1]);没有考虑j为0没有a[i+1][j-1]的存在和j为10时没有a[i+1][j+1]的存在 第二次错:我纠正了第一次的错误,把j为0和10单独考虑,这是数塔类型,我是自下向上推得,所以行数应该从最大的时间m=t:m-1开始的,但我写的是m,我感觉应该没

简单动态规划-LeetCode198

题目:House Robber You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected a