• [Contest on 2020.11.24] Beetle


    ( ext{Description})

    传送门

    ( ext{Solution})

    有一个比较显然的结论:如果路过某处有露水就一定会喝。

    基于这个结论我们知道每一步一定是走到左/右边露水。

    起初想了个这样的 ( ext{DP})(f[i][j])(j) 时刻到 (i) 号露水的最多的水。你会发现不仅时间过不去,状态也无法转移。如果以 (i) 为外循环,那么 (i+1) 无法转移到 (i);如果以 (j) 为外循环,那么会把 (i) 的露水算重。

    遇到两边向中间/中间向两边转移的问题就应该想到区间 ( ext{DP}) 啊。我们定义 (f[i][j][k][2]) 为已经覆盖的区间为 ([i,j])(容易发现覆盖区间一定是连续的),时间为 (k),现在在 (i/j) 的最多的水。

    然后,你会发现,这个 ( ext{DP}) 根本跑不过第一个部分分((nle 10))!仔细想想,原来这个部分分是留给搜索的,那没事了。

    考虑优化时间那一维(其他的好像也不能优化了)。其实我们用时间只是为了计算蒸发了多少露水,将这个计算推到每个露水被喝的时候计算。可以换一个思路,如果我们将运算提前,每走一步就将这一步的距离(即时间)乘上后面还剩多少个露水可以取作为这一步的蒸发多少露水,就可以不用储存时间了。取而代之的是要枚举一共取多少露水,这是为了计算后面还剩多少个露水。

    总时间复杂度 (mathcal O(n^3))

    ( ext{Code})

    #include <cstdio>
    
    #define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
    #define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
    #define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define print(x,y) write(x),putchar(y)
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
    template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
    template <class T> inline T fab(const T x) {return x>0?x:-x;}
    template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
    template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
    template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}
    
    #include <algorithm>
    using namespace std;
    
    const int maxn=305,inf=0x3f3f3f3f;
    
    int n,m,x[maxn],ans,k,flag[maxn][maxn][2],f[maxn][maxn][2];
    
    int DP(int op,int l,int r) {
    	if(r-l==k) return 0;
    	if(flag[l][r][op]==k) return f[l][r][op];
    	flag[l][r][op]=k; f[l][r][op]=inf;
    	int pos=(op?r:l);
    	if(l^1) f[l][r][op]=Min(f[l][r][op],(x[pos]-x[l-1])*(k-(r-l))+DP(0,l-1,r));
    	if(r^n) f[l][r][op]=Min(f[l][r][op],(x[r+1]-x[pos])*(k-(r-l))+DP(1,l,r+1));
    	return f[l][r][op];
    }
    
    int main() {
    	n=read(9),m=read(9);
    	rep(i,1,n) x[i]=read(9);
    	x[++n]=0;
    	sort(x+1,x+n+1);
    	int pos;
    	rep(i,1,n) if(x[i]==0) {pos=i; break;}
    	for(k=1;k<n;++k) ans=Max(ans,m*k-DP(0,pos,pos));
    	print(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    FPGA远程更新之限制条件
    异步FIFO格雷码与空满
    异步FIFO空满设计延迟问题
    从云端到边缘 AI推动FPGA应用拓展
    异步FIFO跨时钟域亚稳态如何解决?
    FPGA该如何应对ASIC的大爆发?
    AbstractQueuedSynchronizer概述
    ssh 解决经常断开与记住密码功能
    CentOS 7 Docker安装
    Redis设计与实现笔记
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14031551.html
Copyright © 2020-2023  润新知