• 动态规划多种题型


                                                                                      数字三角形

                                               数塔

    Problem Description

    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:

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

    已经告诉你了,这是个DP的题目,你能AC吗?
    Input
    输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
    Output
    对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。
    Sample Input
    1
    5
    7
    3 8
    8 1 0
    2 7 4 4
    4 5 2 6 5
    Sample Output
    30
    这是我大一写的第一道动态规划了
    我们用dp[i][j]表示从起始点到i,j位置的最大数字和 ,转移方程便是dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
    其实这还可以从下往上推 那么到起点的数字之和一定是最大的 我这个就是从下往上推的
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<map>
     8 #include<set>
     9 #include<vector>
    10 #include<cstdlib>
    11 #include<string>
    12 #define eps 0.000000001
    13 typedef long long ll;
    14 typedef unsigned long long LL;
    15 using namespace std;
    16 const int N=100+10;
    17 int mp[N][N];
    18 int dp[N][N];
    19 int main(){
    20     int t;
    21     int n;
    22     scanf("%d",&t);
    23     while(t--){
    24         scanf("%d",&n);
    25         for(int i=1;i<=n;i++)
    26         for(int j=1;j<=i;j++)scanf("%d",&mp[i][j]);
    27         int maxx=0;
    28         for(int i=n-1;i>=1;i--)
    29         for(int j=1;j<=i;j++){
    30             mp[i][j]+=max(mp[i+1][j],mp[i+1][j+1]);
    31         }
    32         cout<<mp[1][1]<<endl;
    33     }
    34 }

                                               矩形嵌套 (DAG)

    有n个矩形  每个矩形有长和宽a b;要使x矩形可以嵌套在y矩形内  必须(x.a<y.a&&x.b<y.b 或者 x.a<y.b&&x.b<y.a);

    现在问你选出最多的矩形排成一行 使除了最后以后矩形之外  每个矩形都可以嵌套在下一个矩形

                                   矩形嵌套

    描述
    有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
    输入
    第一行是一个正正数N(0<N<10),表示测试数据组数,
    每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
    随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽
    输出
    每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
    样例输入
    1
    10
    1 2
    2 4
    5 8
    6 10
    7 9
    3 1
    5 8
    12 10
    9 7
    2 2
    
    样例输出
    5

    题解:首先我们先让每个矩形的长的边 按照从大到小的排个序  Vis[i][j]表示第j个矩形可以嵌套在第i个矩形内

    所以我们可以遍历比较一遍  最终根据vis[i][j]得到的就是一个有向无环图

    dp[i]表示从节点i出发的最长路长度 ,那么转移方程就是dp[i]=max(dp[j]+1,vis[i][j]=1)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<map>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<set>
     8 #include<queue>
     9 #include<cstring>
    10 #include<string.h>
    11 #include<algorithm>
    12 #define INF 0x3f3f3f3f
    13 typedef long long ll;
    14 typedef unsigned long long LL;
    15 using namespace std;
    16 const int N=1000+10;
    17 int vis[1005][1006];
    18 struct node{
    19     int x,y;
    20 }a[N];
    21 int ans[N];
    22 bool cmp(node xx,node yy){
    23     if(xx.x==yy.x)return xx.y>yy.y;
    24     else
    25         return xx.x>yy.x;
    26 }
    27 int main(){
    28     int t;
    29     scanf("%d",&t);
    30     while(t--){
    31         memset(ans,0,sizeof(ans));
    32         memset(vis,0,sizeof(vis));
    33         int n;
    34         scanf("%d",&n);
    35         // scanf("%d",&n);
    36         for(int i=0;i<n;i++){
    37             scanf("%d%d",&a[i].x,&a[i].y);
    38             if(a[i].x<a[i].y)swap(a[i].x,a[i].y);
    39         }
    40         sort(a,a+n,cmp);
    41         for(int i=0;i<n;i++)
    42         for(int j=i+1;j<n;j++){
    43             if(a[i].x>a[j].x&&a[i].y>a[j].y)vis[j][i]=1;
    44         }
    45         int maxx=0;
    46         for(int i=0;i<n;i++){
    47             ans[i]=1;
    48             for(int j=0;j<n;j++){
    49                 if(vis[i][j]==1&&ans[i]<ans[j]+1)
    50                 ans[i]=ans[j]+1;
    51             }
    52          }
    53        // for(int i=0;i<n;i++)cout<<ans[i]<<" ";
    54        // cout<<endl;
    55         for(int i=0;i<n;i++)maxx=max(ans[i],maxx);
    56         cout<<maxx<<endl;
    57     }
    58 }

                                             最长公共字串和最长公共子序列

    拿例子来看吧  X:bacabcefabc   Y: baeabcghabc

    最长公共字串:abc(字符串必须是连续的 )

    最长公共子序列:abcabc(可以不连续)

    <1>  最长公共字序列:dp[i][j] 表示储存Xi Yj的最长公共子序列长度

    假如 i=0或者j=0 dp[i][j]=0;

    假如 i>0&&j>0 Xi==Yj dp[i][j]=dp[i-1][j-1]+1;

    假如i>0&&j>0  Xi!=Yj  dp[i][j]=max(dp[i-1][j],dp[i][j-1])(自己想想应该很好理解的);

    来看一道题:

                                 最长公共子序列

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:3
    描述
    咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
    tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
    输入
    第一行给出一个整数N(0<N<100)表示待测数据组数
    接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.
    输出
    每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
    样例输入
    2
    asdf
    adfsd
    123abc
    abc123abc
    样例输出
    3
    6
    代码板子

    <2>最长公共字串

    当i==0或者j==0 dp[i-1][j-1]=0;

    当X[i-1]==Y[j-1]  dp[i][j]=dp[i-1][j-1]+1;

    否则  dp[i-1][j-1]=0;

     

                                             最大矩阵问题

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<map>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<set>
     8 #include<queue>
     9 #include<cstring>
    10 #include<string.h>
    11 #include<algorithm>
    12 #define INF 0x3f3f3f3f
    13 typedef long long ll;
    14 typedef unsigned long long LL;
    15 using namespace std;
    16 const int N=500+50;
    17 int dp[N][N];
    18 int m,n;
    19 int main(){
    20     while(scanf("%d%d",&m,&n)!=EOF){
    21         memset(dp,0,sizeof(dp));
    22         int x;
    23         int maxx=-555555;
    24         int t=-66666;
    25         for(int i=1;i<=m;i++)
    26         for(int j=1;j<=n;j++){
    27             scanf("%d",&x);
    28             t=max(t,x);
    29             dp[i][j]=dp[i-1][j]+x;
    30         }
    31 
    32         for(int i=1;i<=m;i++)
    33         for(int j=i;j<=m;j++){
    34             int sum=0;
    35             for(int k=1;k<=n;k++){
    36                 sum=sum+dp[j][k]-dp[i-1][k];
    37                 if(sum<0)sum=0;
    38                 if(sum>maxx)maxx=sum;
    39             }
    40         }
    41         if(maxx==0)cout<<t<<endl;
    42         else
    43 
    44         cout<<maxx<<endl;
    45     }
    46 }
  • 相关阅读:
    为什么要提倡"Design Pattern"呢? 开闭原则 系统设计时,注意对扩展开放,对修改闭合。
    面向对象、接口编程的重要性 python 为什么引入接口interface
    ON DUPLICATE KEY UPDATE
    Starting Session of user root.
    DRDS和RDS主要用来存储用户交易信息,MongoDB主要用来存储商品维度信息
    抽象不应该依赖于具体,具体应该依赖于抽象。 要针对接口编程,而不是针对实现编程。
    高层次的模块不应该依赖于低层次的模块
    系统设计的次要目的
    存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档
    JVM 的 Xms 和 Xmx 设置一样大小的内存容量
  • 原文地址:https://www.cnblogs.com/Aa1039510121/p/6567404.html
Copyright © 2020-2023  润新知