• 2018.02.02(登山,怪盗基德的滑翔翼等)


    2018.02.02

     动态规划练习

     

    1.登山

    思路:就是一个同时找最长上升子序列和最长下降子序列的综合题。最后加起来取最大值。不过需要注意的是,不管是上山还是下山,第一个点都是要初始化的,这是边界条件。因为下山没有初始化,调了2h+的教训要记得。

    核心代码:

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 int n,num[1001],sum_up[1001],sum_down[1001];
     5 int max=1;
     6 int _Max(int x,int y){return x>y?x:y;} 
     7 int main(){
     8     scanf("%d",&n);
     9     int i,j;
    10     for(i=1;i<=n;i++)
    11         scanf("%d",&num[i]);
    12     sum_up[1]=1;
    13     for(i=2;i<=n;i++){
    14         sum_up[i]=1;
    15         for(j=i-1;j>0;j--)
    16             if(num[j]<num[i])
    17                 sum_up[i]=_Max(sum_up[i],sum_up[j]+1);
    18     }
    19     sum_down[n]=1;
    20     for(i=n-1;i>0;i--){
    21         sum_down[i]=1;
    22         for(j=i+1;j<=n;j++)
    23             if(num[j]<num[i])
    24                 sum_down[i]=_Max(sum_down[i],sum_down[j]+1);
    25         max=_Max(max,sum_up[i]+sum_down[i]-1);
    26     }
    27     max=_Max(max,sum_up[n]+sum_down[n]-1);
    28     printf("%d",max);
    29     return 0;
    30 }
    View Code

    状态:AC

    2.怪盗基德的滑翔翼

    思路:也是一个同时找最长上升子序列和最长下降子序列的综合题。不过这个题不是加起来,而是两条最优方案再取最优。

    核心代码:

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 int n,num[1001];
     5 int sum[1001],sum2[1001];
     6 int max=-99999999;
     7 int _Max(int x,int y){return x>y?x:y;} 
     8 int main(){
     9     int kk;
    10     scanf("%d",&kk);
    11     for(int k=1;k<=kk;k++){
    12         scanf("%d",&n);
    13         int i,j;
    14         for(i=1;i<=n;i++)
    15             scanf("%d",&num[i]);
    16         sum[1]=1;
    17         for(i=2;i<=n;i++){
    18             sum[i]=1;
    19             for(j=1;j<i;j++)
    20                 if(num[j]>num[i])
    21                     sum[i]=_Max(sum[i],sum[j]+1);
    22         }
    23         sum2[1]=1;
    24         for(i=2;i<=n;i++){
    25             sum2[i]=1;
    26             for(j=1;j<i;j++)
    27                 if(num[j]<num[i])
    28                     sum2[i]=_Max(sum2[i],sum2[j]+1);
    29         }
    30         for(i=1;i<=n;i++){
    31             max=_Max(max,sum[i]);
    32             max=_Max(max,sum2[i]);
    33         }
    34         printf("%d
    ",max);
    35         max=-99999999;
    36     }
    37     return 0;
    38 }
    View Code

    状态:AC

    3.移动路线

    思路:数字三角形的变式,状态转移方程都是一样的。

    核心代码:

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 int map[21][21];
     5 int n,m;
     6 main(){
     7     scanf("%d%d",&n,&m);
     8     int i,j;
     9     map[0][1]=1;
    10     for(i=1;i<=n;i++)
    11         for(j=1;j<=m;j++)
    12             map[i][j]=map[i-1][j]+map[i][j-1];
    13     printf("%d",map[n][m]);
    14     return 0;
    15 }
    View Code

    状态:AC

    4.最低通行费

    思路:同(3)。只不过要额外加一个边界判定条件:2*n-1的时间,在找最短路时不能超时。

    核心代码:

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 int map[101][101],f[101][101];
     5 int n;
     6 int _Min(int x,int y){return x<y?x:y;}
     7 void search(int time,int x,int y){
     8     if(time==0&&(x!=n||y!=n))
     9         return;
    10     if(f[x-1][y]==-1 &&x-1>=1)
    11         search(time-1,x-1,y);
    12     if(f[x][y-1]==-1 &&y-1>=1)
    13         search(time-1,x,y-1);
    14     if(x-1>=1&&y-1>=1)
    15         f[x][y]=map[x][y]+_Min(f[x][y-1],f[x-1][y]);
    16     else if(x-1>=1&&y-1<1)
    17         f[x][y]=map[x][y]+f[x-1][y];
    18     else if(x-1<1&&y-1>=1)
    19         f[x][y]=map[x][y]+f[x][y-1];
    20 }
    21 int main(){
    22     scanf("%d",&n);
    23     int i,j;
    24     for(i=1;i<=n;i++){
    25         for(j=1;j<=n;j++){
    26             scanf("%d",&map[i][j]);
    27             f[i][j]=-1;
    28         }
    29     }
    30     f[1][1]=map[1][1];
    31     search(2*n-1,n,n);
    32     printf("%d
    ",f[n][n]); 
    33     return 0;
    34 }
    View Code

    状态:AC

    5.摘花生

    思路:还是数字三角形。(话说好像做的都是同一个模板题)

    核心代码:

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 int map[101][101],f[101][101];
     5 int n,m;
     6 int _Max(int x,int y){return x>y?x:y;}
     7 void search(int x,int y){
     8     if(x<1||y<1)
     9         return;
    10     if(f[x-1][y]==-1 &&x-1>=1)
    11         search(x-1,y);
    12     if(f[x][y-1]==-1 &&y-1>=1)
    13         search(x,y-1);
    14     if(x-1>=1&&y-1>=1)
    15         f[x][y]=map[x][y]+_Max(f[x-1][y],f[x][y-1]);
    16     else if(x-1>=1&&y-1<1)
    17         f[x][y]=map[x][y]+f[x-1][y];
    18     else if(x-1<1&&y-1>=1)
    19         f[x][y]=map[x][y]+f[x][y-1];
    20 }
    21 int main(){
    22     int k;
    23     int i,j;
    24     scanf("%d",&k);
    25     for(int kk=1;kk<=k;kk++){
    26         scanf("%d%d",&n,&m);
    27         for(i=1;i<=n;i++){
    28             for(j=1;j<=m;j++){
    29                 scanf("%d",&map[i][j]);
    30                 f[i][j]=-1;
    31             }
    32         }
    33         f[1][1]=map[1][1];
    34         search(n,m);
    35         printf("%d
    ",f[n][m]);
    36     }
    37     return 0;
    38 }
    View Code

    状态:AC

    6.Maxinum sum

    状态:UNAC

    7.计算字符串距离

    状态:UNAC

     8.公共子序列

    题解代码:

     1 #include <cstdio>
     2 #include<cmath>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 int main(){
     7     char a[210],b[210];
     8     int f[201][201];
     9     int l1,l2,i,j;
    10     while(cin>>a+1>>b+1){
    11         memset(f,0,sizeof(f));
    12         l1=strlen(a);
    13         l2=strlen(b);
    14         for(i=1;i<l1;i++)
    15             for(j=1;j<l2;j++)
    16                 if(a[i]==b[j]&&f[i-1][j-1]+1>f[i][j])
    17                     f[i][j]=f[i-1][j-1]+1;
    18                 else
    19                     f[i][j]=max(f[i-1][j],f[i][j-1]);
    20         cout<<f[l1-1][l2-1]<<endl;
    21     }
    22     return 0;
    23 }
    View Code

    状态:UNAC(照着书上打了一上午,还是过不了?借鉴了一个题解,评测可以过,本地过不了???)

  • 相关阅读:
    字符串题表
    插头dp题表
    点分治题表
    Kd-tree题表
    【BZOJ 4605】崂山白花蛇草水 替罪羊树套线段树
    假的kd-tree小结
    【BZOJ 1492】 [NOI2007]货币兑换Cash 斜率优化DP
    CDQZ 2017 游记
    【BZOJ 1146】[CTSC2008]网络管理Network
    联赛之前的题表(已完成)汇总(可能有遗漏)
  • 原文地址:https://www.cnblogs.com/yzyl-Leo-wey/p/8408662.html
Copyright © 2020-2023  润新知