zoukankan      html  css  js  c++  java
  • BZOJ 3111: [Zjoi2013]蚂蚁寻路

    Sol

    DP.

    首先观察转折,画画图,看看移动路线,可以非常轻易的发现如果走到起点的下方是回不去的..

    然后它就相当于一个底部是平的,顶部凹凹凸凸的形状,每右转两次或左转两次就会形成小矩阵,这样就可以来DP了.

    首先一个非常简单的思路,就是f[k][i][j]表示取到第j列高度为h最大权值,枚举上一个转折点,复杂度 (O(n^5k)) 因为上一个点一定是与他同一行的,枚举行,枚举次数,枚举列,枚举高度,枚举上一个位置的列,枚举上一个位置的行.

    我们可以优化,让他一次DP一行,其实可以发现就是取高度大于或小于当前高度,列小于当前的点最大值,这个最大值我们可以记录下来然后 (O(1)) 转移,再加上每列前缀和,就是 (O(n^3k)) 的了.

    Code

    /**************************************************************
        Problem: 3111
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:172 ms
        Memory:1460 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
     
    const int N = 105;
    const int K = 25;
    const int INF = 0x3fffffff;
     
    int n,m,k,ans;
    int a[N][N],d[N][N];
    int f[N][N],g[N][N];
     
    inline int in(int x=0,char ch=getchar(),int v=1){
        while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();if(ch=='-') v=-1,ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*v; }
    int main(){
    //  freopen("in.in","r",stdin);
        n=in(),m=in(),k=in();ans=-INF;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=in();
    //  for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) d[i][j]=d[i-1][j]+a[i][j];
        for(int i=1;i<=n;i++){
            memset(f,0x8f,sizeof(f)),memset(g,0x8f,sizeof(g)),memset(d,0,sizeof(d));
            for(int u=1;u<=m;u++) for(int v=i;v;v--) d[v][u]=d[v+1][u]+a[v][u];
            for(int u=1;u<=m;u++) for(int v=1;v<=i;v++) g[v][u]=max(g[v][u-1],0)+d[v][u];
            for(int q=1;q<=k;q++){
                for(int u=1;u<=m;u++) for(int v=1,tmp=-INF;v<=i;v++) tmp=max(tmp,g[v-1][u-1]),f[v][u]=max(f[v][u-1],tmp)+d[v][u];
                for(int u=1;u<=m;u++) for(int v=i,tmp=-INF;v;v--) tmp=max(tmp,f[v+1][u-1]),g[v][u]=max(tmp,g[v][u-1])+d[v][u];
            }
            for(int u=1;u<=m;u++) for(int v=1;v<=i;v++) ans=max(ans,g[v][u]);
        }cout<<ans<<endl;
        return 0;
    }   
    

      

  • 相关阅读:
    图论100题 1~5题
    定价 题解
    题解 编码问题【NOIP1995普及+提高】
    【题解】2020牛客NOIP赛前集训营-普及组(第二场)
    数论学习笔记
    el-tree 点击选中的数据集合
    nginx 本地配置(解决跨域问题)
    原生对象写法,dom调用方法
    手写无缝轮播banner
    element Notification 通知文字换行小技巧
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5811590.html
Copyright © 2011-2022 走看看