• DP练习~今天s酱不在家~


    RT,今天s酱不在家~

    于是w就可以为所欲为的刷水题啦~

    因为w的DP学的实在是……,于是今天w去刷了几道DP题练手>_<


    1.能量项链(luogu P1063)

    这题面……考验语文能力的时刻到了x

    一道区间DP

    这个环结构看起来就很麻烦的样子……

    那就拆了O(∩_∩)O~

    每次读入一个a[i]的时候,顺手把a[n+i]也赋成这个值

    这样处理完后就是一个长度为原环两倍的链

    在这个链上能找到所有长度为n+1的可能排列

    //长度n+1是因为最后一个珠子的尾标是第一个的头标,在链中即下一个的头标

    接下来就DP吧

    f[i][j]表示区间长度为i,区间左端点的头标记是j

    有了这两个当然就能算出右端点的尾标记

    然后枚举一波断点(区间DP的套路

    因为每个珠子有两个标记,又只存了一个数

    导致各种+1-1的小细节

    qwq看了好久才明白

    最后再统计一波答案

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=202;
    int n,a[N],ans;
    int f[N][N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
          scanf("%d",&a[i]);
          a[i+n]=a[i];
        }
        for(int i=2;i<=n+1;++i)//区间长度 
        {
          for(int l=1;l+i-1<=2*n;++l)//头标记 
          {
            int r=l+i-1;//尾标记 
            for(int k=l+1;k<=r-1;++k)//中间断点的标记 
            f[l][r]=max(f[l][r],f[l][k]+f[k][r]+a[l]*a[k]*a[r]);
          } 
        }
        for(int i=1;i<=n;++i)//区间开始位置 
        ans=max(ans,f[i][i+n]);
        cout<<ans<<endl; 
        return 0;
    }
    energy
     

    2.垃圾陷阱(luogu P1156)
     
     

    为什么是卡门不是Bessie(

    刚一看题面各种mengbier,连DP存什么都想不出来

    跑去看题解,类背包?++mengbier

    看了好久才看懂……做法很神奇x

    学了一种刷表的做法

    (乱入的科普:刷表指用现在的状态去更新之后的状态,与之相反的是填表,指用之前的状态更新现在的状态)

    DP数组?不存在的 这里的所谓DP数组其实是一个bool数组

    里面存的,既不是高度,也不是能量

    f[i][j]表示的是在高度为i,时间为j的情况下能否存活

    如果能存活的话就向下转移

    两个转移方向:堆起来(i+高度)或者吃掉(j+时间)

    转移完发现高度超出井深了,因为经过了排序,所以得出的一定是最早的时间,输出就好了

    一套循环下去这牛还没有出去,说明它已经在井里gg了

    时间从后向前倒,看它活在这世上的最后一秒是什么时候

    //传说中的刷表法qwq 
    #include<cstdio>
    #include<iostream>
    #include<algorithm> 
    using namespace std;
    int d,g,s=10;
    bool f[400][6000];//f[i][j]->高度为i的情况下能存活j的时间 
    struct rub{
           int t,h,f;
    }r[105];
    bool cmp(rub x,rub y)
    {
         return x.t<y.t;
    }
    int main()
    {
        cin>>d>>g;
        for(int i=1;i<=g;++i){
          scanf("%d%d%d",&r[i].t,&r[i].f,&r[i].h);
          s+=r[i].f; //计算可能存活的最大时间 
        }
        sort(r+1,r+g+1,cmp);
        f[0][10]=1;
        for(int i=1;i<=g;++i)//垃圾 
        for(int j=d-1;j>=0;--j)//高度 
        for(int k=s;k>=r[i].t;--k)//时间 
        {
          if(!f[j][k])continue;
          if(j+r[i].h>=d)
          {
            printf("%d",r[i].t);
            system("pause");
            return 0;
          }
          else 
          {
            f[j+r[i].h][k]=1;
            f[j][k+r[i].f]=1;
          }
        }
        for(int i=s;i>=1;--i)
        if(f[0][i])
        {
          printf("%d",i);
          system("pause");
          return 0;
        } 
        return 0;      
    }
    rubbish well

     3.过河(luogu P1052)

    一开始一看,这不是某只⑨的一道题吗?

    然后一看数据范围,L<=10^9,1 <= M <= 100

    (步长10桥长10^9,心疼这只青蛙一下x)

    正常的DP方程很好写

    f[j]=min(f[j],f[i]+stn[j])

    然而10^9的数据,时间空间都会炸

    但是因为长长的桥上只有很少的石子

    所以在两个石子之间青蛙君会跳过一段很长的没有石子的距离

    就可以把这段距离压缩一下

    把距离>100(10*10)的两颗石子中间的距离压到100

    ……据说还可以压到90?并不理解qwq,反正有100就够用了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=50000;
    int l,s,t,m,a[200],stn[N],f[N],tmp;
    int main()
    {
        scanf("%d%d%d%d",&l,&s,&t,&m);
        for(int i=1;i<=m;++i)
        scanf("%d",&a[i]);
        sort(a+1,a+m+1);
        if(s==t)
        {
          int ans=0;
          for(int i=1;i<=m;++i)
          if(!(a[i]%s))++ans;
          printf("%d",ans);
          return 0;
        }
        for(int i=1;i<=m;++i)
        {
          int x=a[i]-a[i-1];
          if(x>100)tmp+=100;
          else tmp+=x;
          ++stn[tmp];
          if(i==m)l=tmp+1;
        }
        int ans=200;
        for(int i=1;i<=l+15;++i)f[i]=200;
        f[0]=0;
        for(int i=0;i<=l+15;++i)
        {
          for(int j=i+s;j<=i+t;++j)
          f[j]=min(f[j],f[i]+stn[j]);
        }
        for(int i=l;i<=l+15;++i)ans=min(ans,f[i]);
        cout<<ans; 
        return 0;
    } 
    过河

    呀s酱回来了>_<保存保存……

     

  • 相关阅读:
    Angular14 Angular相关命令
    Angular14 Visual Studio Code作为Angular开发工具常用插件安装、json-server安装与使用、angular/cli安装失败问题、emmet安装
    Material使用03 MdCardModule模块、MdInputModule模块
    Material使用02 图标MdIconModule、矢量图作为图标使用及改进
    Material使用01 侧边栏MdSidenavModule、工具栏MdTollbarModule
    阿里巴巴Druid数据库连接池的使用
    利用generator自动生成model(实体)、dao(接口)、mapper(映射)
    c++拷贝函数详解(转)
    c++友元函数友元类
    c++中虚函数与纯虚函数的区别(转)
  • 原文地址:https://www.cnblogs.com/ck666/p/7500588.html
Copyright © 2020-2023  润新知