zoukankan      html  css  js  c++  java
  • P3205 [HNOI2010]合唱队

    P3205 [HNOI2010]合唱队

    题解

    区间DP唉

    不会写怎么办QAQ

    先暴搜

    暴力:

    根据理想队形找原序列,找第一个人不好找,但是可以确定最后一个人是谁,然后就可以一次推测前一个人,知道搜出一个合法序列

    显然,最后一个人只可能是理想序列的最左端或最右端

    然后在剩下的区间里面,找到合法的下一个人,继续搜,知道搜到只剩一个人的区间,判断一下合不合法,就可以判断能否得到一个合法序列

    为了有效避免一开始的分类讨论(也就是从最左端开始还是从最右端开始算最后一个)

    我们默认最后一个人的标号为 0 ,因为此时第0个人的身高为0,在整个区间最左端,肯定比左右区间的人都矮

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const int mod=19650827;
    int n;
    int a[1005];
    ll ans=0;
    
    ll dfs (int now,int l,int r)
    //当前搜索的人的标号,下面要搜索的区间[l,r] 
    {
        if(l==r) return (now>l&&a[now]>a[l])||(now<l&&a[now]<a[l]);
        //区间只剩一个人喽,也要最后判断一下 
        if(now>r&&a[now]<a[l]&&a[now]<a[r]) return 0;
        if(now<l&&a[now]>a[l]&&a[now]>a[r]) return 0;
        //不合法,直接计0 
        ll res=0;
        if(now>r&&a[now]>a[l]||now<l&&a[now]<a[l]) 
           res=res+dfs(l,l+1,r)%mod;
        if(now>r&&a[now]>a[r]||now<l&&a[now]<a[r])
           res=res+dfs(r,l,r-1)%mod;
        return res%mod;
        
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        ans=0;
        ans=ans+dfs(0,1,n)%mod;
        printf("%lld
    ",ans);
        
        return 0;
    }

    记忆化:

    不好意思我 WA 了几个点

    考虑区间DP:

    设置两个数组:

    f[ i ][ j ] 区间 [ i , j ] 最后一个选择左端点的合法序列数

    g[ i ][ j ] 区间 [ i , j ] 最后一个选择右端点的合法序列数

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const int mod=19650827,maxn=214748360,minn=-1;
    int n;
    int a[1005];
    ll f[1005][1005],g[1005][1005];
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        a[0]=3000;
        for(int i=1;i<=n;i++) f[i][i]=1;
    
        for(int l=2;l<=n;l++)
          for(int i=1;i+l-1<=n;i++)
          {
              int j=i+l-1;
            f[i][j]=(f[i+1][j]*(a[i]<a[i+1])%mod+g[i+1][j]*(a[i]<a[j])%mod)%mod;
            g[i][j]=(f[i][j-1]*(a[j]>a[i])%mod+g[i][j-1]*(a[j]>a[j-1])%mod)%mod;
          }
        
        printf("%lld
    ",(f[1][n]+g[1][n])%mod);
        
        return 0;
    }
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11535601.html
Copyright © 2011-2022 走看看