动态规划例题

最大连续子序列之和

题目:

给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序中元素和最大的一个。例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20。

状态转移方程: sum[i]=max(sum[i-1]+a[i],a[i])

代码:

#include <cstdio>

int main()
{
    int i, sum = 0, max = 0;
    int data[] = { 1, -2, 3, -1, 7 };
    for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
    {
        sum += data[i];
        if (sum > max)
            max = sum;
        if (sum < 0)
            sum = 0;
    }
    printf("%d", max);
    return 0;
}

作者:nash_
链接:https://blog.csdn.net/zmazon/article/details/8247015
来源:CSDN

塔树选择和最大问题

题目:

数塔问题 :要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

   5
  8 4
 3 6 9
7 2 9 5

分析:

直接分析,从上到下的考虑,发现无从下手好像只能遍历,但是反方向考虑则,则发现有趣的地方,假设dp[i][j]为最下面一层到第i层j位置上的最大值,考虑上图6这个位置,那么其dp[3][2]应该是什么呢?是下面相邻的两个位置的最大值+6,即dp[3][2] = max(dp[3+1][2],dp[3+1][2+1]) + a[3][2]。

据此可以推导其公式为
dp[i][j] = max(dp[i+1][j],dp[i+1][j+1]) + a[i][j]

根据上述公式编程思路如下:
1、初始化最下面一排dp
2、由下往上,安装上述公式对dp进行赋值
3、dp[1][1]为最终所求

转移方程:sum[i] = max(a[左孩子] , a[右孩子]) + a[i]

代码:

//最下面一层直接赋值
int rs = 0;
for (int i = 0; i < FLOOR; i++)
    dp[FLOOR - 1][i] = a[FLOOR - 1][i];

//从倒数第二行起, 按照状态转移方程
//dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + a[i][j]向上递推
//直到dp[0][0], 此时dp[0][0]就是结果
for (int i = FLOOR - 2; i >= 0; i--)
    for (int j = 0; j <= i; j++)
        dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + a[i][j];

作者:鱼游硅谷
链接:https://www.jianshu.com/p/7ffba3910997
来源:简书

爬楼梯

题目:

你正在爬楼梯。 它需要n步才能达到顶峰。
每次你可以爬1或2步。 您可以通过多少不同的方式登顶?

代码:

class Solution:
    # @param n, an integer
    # @return an integer
    def climbStairs(self, n):
        dp = [0, 1, 2]
        if n <= 2:
            return dp[n]
        dp += [0 for i in range (n-2)]
        for i in range (3, n + 1):
            dp[i] += dp[i-1] + dp[i-2]

        return dp[n]

作者:鱼游硅谷
链接:https://www.jianshu.com/p/7ffba3910997
来源:简书

最长上升子序列(LIS)

题目:

LIS(Longest Increasing Subsequence)最长上升子序列
一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 <= i1 < i2 < … < iK <= N。
比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度。

O(N^2)做法:dp动态规划

状态设计:dp[i]代表以a[i]结尾的LIS的长度
状态转移:dp[i]=max(dp[i], dp[j]+1) (0<=j< i, a[j]< a[i])
边界处理:dp[i]=1 (0<=j< n)
时间复杂度:O(N^2)
举例: 对于序列(1, 7, 3, 5, 9, 4, 8),dp的变化过程如下

dp[i]初始值j=0j=1j=2j=3j=4j=5
dp[0]1
dp[1]12
dp[2]122
dp[3]1223
dp[4]12334
dp[5]122333
dp[6]1233444

求完dp数组后,取其中的最大值就是LIS的长度。【注意答案不是dp[n-1],这个样例只是巧合】

代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXX=100000+5;
const int INF=INT_MAX;

int a[MAXX],dp[MAXX]; // a数组为数据,dp[i]表示以a[i]结尾的最长递增子序列长度

int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
        {
            cin>>a[i];
            dp[i]=1; // 初始化为1,长度最短为自身
        }
        int ans=1;
        for(int i=1; i<n; i++)
        {
            for(int j=0; j<i; j++)
            {
                if(a[i]>a[j])
                {
                    dp[i]=max(dp[i],dp[j]+1);  // 状态转移
                }
            }
            ans=max(ans,dp[i]);  // 比较每一个dp[i],最大值为答案
        }
        cout<<ans<<endl;
    }
    return 0;
}

作者:wbin233
链接:https://blog.csdn.net/wbin233/article/details/77570070
来源:CSDN

背包问题

题目:

有N件物品和一个容量为V的背包。第i件物品的大小是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

分析:

用DP[I][J] 表示前I件物品放入一个容量为J的背包可以获得的最大价值。则

  DP[I][J]=     DP[I-1][J]  ,J<C[I]
                MAX(DP[I-1][J],DP[I-1][J-C[I]]+W[I])  , J>=C[I]

这样实现的空间复杂度为O(VN),实际上可以优化到O(V)

代码:

const int MAXW=13000;    //最大重量
const int MAXN=3450;     //最大物品数量
 
int c[MAXN];     //物品的存放要从下标1开始
int w[MAXN];     //物品的存放要从下标1开始
int dp[MAXW];
 
//不需要将背包装满,则将DP数组全部初始化为0
//要将背包装满,则初始化为DP[0]=0,DP[1]…DP[V]=-1(即非法状态)
int Packet(int n,int v) {
      int i,j;
      memset(dp,0,sizeof(dp));
      for(i=1;i<=n;++i) {
          for(j=v;j>=c[i];--j) {  //这里是倒序,别弄错了
              dp[j]=MAX(dp[j],dp[j-c[i]]+w[i]);
          }
      }
 
      return dp[v];
}

作者:鱼游硅谷
链接:https://www.jianshu.com/p/7ffba3910997
来源:简书

最长公共子序列(LCS)

题目:

LCS:给出两个序列S1和S2,求出的这两个序列的最大公共部分S3就是就是S1和S2的最长公共子序列了。公共部分必须是以相同的顺序出现,但是不必要是连续的。

选出最长公共子序列。对于长度为n的序列,其子序列共有2的n次方个,这样的话这种算法的时间复杂度就为指数级了,这显然不太适合用于序列很长的求解了。

分析:

既然学到了动态规划,就来看看能否用动态规划的思想来解决这个问题。要使用动态规划,必须满足两个条件:有最优子结构和重叠子问题。为了便于学习,我们先来了解下这两个概念。

如果问题的一个最优解中包含了子问题的最优解,则该问题具有最优子结构。当一个递归算法不断地调用同一问题时,我们说该最优问题包含重叠子问题。

说明:动态规划要求其子问题既要独立又要重叠,这初看上去貌似存在矛盾,其实不然。只是这里说的是两个不同的概念。独立指的是同一问题的两个子问题不共享资源。而重叠子问题指的是子问题可以作为不同的问题的子问题出现。

设X = <x1,x2...xm>, Y = <y1,y2...yn>为两个序列,并设Z = <z1,z2...zk>为X和Y的任意一个LCS。可以得出:
1、如果xm = yn,那么zk = xm = yn而且Z(k-1)是X(m-1)和Y(n-1)的一个LCS;
2、如果xm != yn,那么zk != xm蕴含Z是X(m-1)和Y的一个LCS;
3、如果xm != yn,那么zk != yn蕴含Z是X和Y(n-1)的一个LCS。

注:上面的Z(k-1)表示序列Z<z1,z2...zn>,其中n=k-1。其它的X()和Y()也是一样的。
很容易证明上述三点是成立的,详细证明见算法导论。所以LCS具有最优子结构。从上面也可以看出LCS问题中的重
叠子问题的性质。所以我们可以用动态规划来解决LCS问题。由LCS问题的最优子结构可得出递归式:

代码:

#include <iostream>
using namespace std;

#define M 7  
#define N 6  

int lcs(char *x,char *y,int c[M+1][N+1],int b[M+1][N+1])
{
    int m=M,n=N;
    for(int i=0;i<=m;i++)
        c[i][0]=0;
    for(int j=0;j<=n;j++)
        c[0][j]=0;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
        {
            if(x[i]==y[j])
            {
                c[i][j]=c[i-1][j-1]+1;
                b[i][j]=0;
            }
            else if(c[i-1][j]>=c[i][j-1])
            {
                c[i][j]=c[i-1][j];
                b[i][j]=1;
            }
            else
            {
                c[i][j]=c[i][j-1];
                b[i][j]=-1;
            }
        }
    return c[m][n];
}

void printLcs(int b[][7],char *x,int i,int j)
{
    if(i==0||j==0)
        return;
    if(b[i][j]==0)
    {
        printLcs(b,x,i-1,j-1);
        cout<<x[i];
    }
    else if(b[i][j]==1)
        printLcs(b,x,i-1,j);
    else
        printLcs(b,x,i,j-1);
}

int main()
{
     
    char x[M+1]={'0','A','B','C','B','D','A','B'};
    char  y[N+1]={'0','B','D','C','A','B','A'};   
    int c[M+1][N+1];//注意大小要为strlen+1;因为要存0
    int b[M+1][N+1];
    
    cout<<lcs(x,y,c,b)<<endl;
    cout<<"X:"<<x<<endl;
    cout<<"y:"<<y<<endl;
     
    for(int i=1;i<=7;i++)
    {
        for(int j=1;j<=6;j++)
            cout<<b[i][j]<<ends;
        cout<<endl;
    }
    
    cout<<"最长子序列为:"<<endl;
    printLcs(b,x,7,6);
    return 0;
}

注意我们的b[0][i] b[i][0]没有存储任何东西。
输出:4
BCBA.

懒~,请翻原网:https://www.cnblogs.com/youxin/p/3269294.html

Diff

Description of the topic:

In computing,diffis a file comparison utility that outputs the differences between two files. It is typically used to show the changes between a file and a former version of the same file.Diffdisplays the changes made per line for text files.
The operation ofdiffis based on solvingthe longest common subsequence problemwhich is as follows: Given two sequencesA = a1, a2, ⋯, aMandB = b1, b2, ⋯, bN, find the length, k, of the longest sequenceC = c1, c2, ⋯, ck such that C is a subsequence of both A and B. As an example, if

A = d, y, n, a, m, i, c

and

B = p, r, o, g, r, a, m, m, i, n, g

then the longest common subsequence is a, m, i and has length 3.
From the longest common subsequence it's only a small step to get diff-like output:

dyn-progr+m+c-ng+

where - means a deletion from and + means an addition to the first string.
Now you are supposed to simulate the diff operation.

Input Specification:

Each input file contains one test case. Each case contains the contents of two files. The case starts with two non-negative integers N and M (both ≤50), then followed by N + M lines, each contains a string of no more than 80 characters. The first N lines are the contents of the first file, while the second M lines are of the second file.

Output Specification:

For each test case, if there is no difference found between the two files, print in a line "No difference found". If there is nothing in common between the two files, print in a line "Totally different". Otherwise, first print in a line the length of the longest sequence. Then for each line of the first file, print the line number, and output the differences in the diff-like format line by line, as shown by the sample output.

Sample Input 1:

1 1
This is a test
This is a test

Sample Output 1:

No difference found

Sample Input 2:

1 1
ab
cd

Sample Output 2:

Totally different

Sample Input 3:

5 5
This line is the same
This is a test
which is more complicated
zzz
than ...
This line is the same
This is another test
of the project
which is much more complex
than the previous one

Sample Output 3:

60
line #1:

line #2:
nother+
line #3:
of the project+
 much+icat-d-
line #4:
zzz-
line #5:
x+
...-the previous one+

Find More Coins

Description of the topic:

Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she must pay the exact amount. Since she has as many as \[10^2\] coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find some coins to pay for it.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: N ( ≤\[10^4\], the total number of coins) and M ( ≤\[10^2\], the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the face values V1 ≤ V2 ≤ ⋯ ≤ Vk such that V1 + V2 + ⋯ + Vk = M. All the numbers must be separated by a space, and there must be no extra space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output "No Solution" instead.
Note: sequence {A[1], A[2], ...} is said to be "smaller" than sequence {B[1], B[2], ...} if there exists k≥1 such that A[i]=B[i] for all i < k , and A[k] < B[k].

Sample Input 1:

8 9
5 9 8 7 2 3 4 1

Sample Output 1:

1 3 5

Sample Input 2:

4 8
7 2 4 3

Sample Output 2:

No Solution

Favorite Color Stripe

Description of the topic:

Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva's favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva's favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer \[N\] ( ≤ \[200\] ) which is the total number of colors involved (and hence the colors are numbered from 1 to \[N\]). Then the next line starts with a positive integer \[M\] ( ≤ \[200\] ) followed by \[M\] Eva's favorite color numbers given in her favorite order. Finally the third line starts with a positive integer \[L\] ( ≤ \[10^4\] ) which is the length of the given stripe, followed by \[L\] colors on the stripe. All the numbers in a line a separated by a space.

Output Specification:

For each test case, simply print in a line the maximum length of Eva's favorite stripe.

Sample Input:

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

Sample Output:

7

Favorite Color Stripe

Description of the topic:

Insertion Sequences of a Binary Search Tree

  • The left subtree of a node contains only nodes with keys less than the node's key;
  • The right subtree of a node contains only nodes with keys greater than the node's key;
  • Both the left and right subtrees are also binary search trees.
    There exists different insertion sequences when we try to build a binary search tree. As for the binary search tree shown below,

a valid insertion sequence can be 3 2 1 4 6 5, or 3 2 4 1 6 5 , but cannot be 3 2 4 5 6 1.

Now you are given the pre-order traversal sequence of a binary search tree. Please write a program to calculate the total count of insertion sequences of this tree. Since the total can be very large, you should output the result modulo 1000000007 ( \[10^9\] + 7 ) .

Input Specification:

Each input file contains one test case. Each test case consists of two lines. In the first line, an integer \[N\] is given, denoting the count of elements in the binary search tree; and the second line gives the pre-order traversal sequence of the tree, in which numbers are separated by a space.

Output Specification:

Output the total count of insertion sequences in a line.

Sample Input:

6
3 2 1 4 6 5

Sample Output:

10

Insertion Sequences of a Binary Search Tree

Description of the topic:

A binary search tree (BST) can be defined as a binary tree with the following properties:

  • The left subtree of a node contains only nodes with keys less than the node's key;
  • The right subtree of a node contains only nodes with keys greater than the node's key;
  • Both the left and right subtrees are also binary search trees.
    There exists different insertion sequences when we try to build a binary search tree. As for the binary search tree shown below,

1521187-20181210204433121-1421053220.png

a valid insertion sequence can be 3 2 1 4 6 5, or 3 2 4 1 6 5 , but cannot be 3 2 4 5 6 1.

Now you are given the pre-order traversal sequence of a binary search tree. Please write a program to calculate the total count of insertion sequences of this tree. Since the total can be very large, you should output the result modulo 1000000007 ( \[10^9\] + 7 ) .

Input Specification:

Each input file contains one test case. Each test case consists of two lines. In the first line, an integer \[N\] is given, denoting the count of elements in the binary search tree; and the second line gives the pre-order traversal sequence of the tree, in which numbers are separated by a space.

Output Specification:

Output the total count of insertion sequences in a line.

Sample Input:

6
3 2 1 4 6 5

Sample Output:

10

转载于:https://www.cnblogs.com/JingWenxing/p/10095887.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值