zoukankan      html  css  js  c++  java
  • [JXOI 2018] 守卫 解题报告 (DP)

    interlinkage:

    https://www.luogu.org/problemnew/show/P4563

    description:

    solution:

    • 注意到对于范围$[l,r]$,$r$这个亭子一定要设置保镖
    • 设$f_{l,r}$为活动范围为$[l,r]$所需的最小保镖数
    • 枚举右端点$r$,然后从右向左遍历左端点$l$。设$p$为在$[l,r]$中$r$处能看到的最左的点
    • 这样的话我们就必须在$p$或者$p-1$处放置保镖
    • 于是$f_{l,r}=min(f_{l,p-1},f_{l,p})+f_{p+1,r}$
    • 注意一下$p$的更新,若$l$到$r$连线的斜率小于$p$到$r$连线的斜率,那么就要更新$p=l$了

    code:

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    
    const int N=5000+15;
    int n;
    int h[N],f[N][N];
    inline int read()
    {
        char ch=getchar();int s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    double slope(int l,int r) {return (double)(h[r]-h[l])/(r-l);}
    bool cansee(int l,int p,int r) 
    {
        return slope(l,r)<slope(p,r);
    }
    int main()
    {
        n=read();
        for (int i=1;i<=n;i++) h[i]=read();
        int ans=0;
        for (int r=1;r<=n;r++)
        {
            f[r][r]=1;ans^=f[r][r];
            int p=0;
            for (int l=r-1;l>=1;l--)
            {
                if (!p||cansee(l,p,r)) p=l;
                f[l][r]=min(f[l][p-1],f[l][p])+f[p+1][r];
                ans^=f[l][r];
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    SVN服务器搭建和使用(一)
    Python3.x和Python2.x的区别
    myeclipse启动不了的解决方法
    学习第49天
    学习第48天
    学习第47天
    学习第46天
    学习第45天
    学习第44天
    学习第43天
  • 原文地址:https://www.cnblogs.com/xxzh/p/10705708.html
Copyright © 2011-2022 走看看