zoukankan      html  css  js  c++  java
  • 洛谷 P1410 子序列(DP)

      这题的题解的贪心都是错误的...正解应该是个DP

      考虑有哪些有关的条件:两个序列的当前长度, 两个序列的末尾数, 把这些都压进状态显然是会GG的

      考虑两个长度加起来那一位的数一定是其中一个序列的末尾, 而我们要末尾的数尽量小, 所以完全可以把这个DP缩成两维

      设f[i][j]为当前选到第i位, a[i]选入第一个序列, 则末尾为a[i], 第一个序列长度为j, 则第二个序列长度为i-j时第二个序列末尾的数最小为多少。

      则有 if(a[i]<a[i+1]) f[i+1][j+1]=min(f[i+1][j+1], f[i][j])

         if(f[i][j]<a[i+1]) f[i+1][i+1-j]=min(f[i+1][i+1-j], a[i]) (此时第一个序列和第二个序列互换了)

      互换的思想真的非常喵喵哇....第一次见到T T

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=2010, inf=1e9;
    int n;
    int f[maxn][maxn], a[maxn];
    inline void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;
    }
    inline int min(int a, int b){return a<b?a:b;}
    int main()
    {
        while(scanf("%d", &n)!=EOF)
        {
            for(int i=1;i<=n;i++) read(a[i]);
            for(int i=1;i<=n;i++) for(int j=0;j<=i;j++) f[i][j]=inf;
            for(int i=0;i<n;i++)
                for(int j=0;j<=i;j++)
                {
                    if(a[i]<a[i+1]) f[i+1][j+1]=min(f[i+1][j+1], f[i][j]);
                    if(f[i][j]<a[i+1]) f[i+1][i-j+1]=min(f[i+1][i-j+1], a[i]);
                }
            printf("%s
    ", (f[n][n>>1]!=inf)?"Yes!":"No!");
        }
    }
    View Code
  • 相关阅读:
    Sql Server 2008卸载后再次安装一直报错
    listbox 报错 Cannot have multiple items selected when the SelectionMode is Single.
    Sql Server 2008修改Sa密码
    学习正则表达式
    Sql Server 查询第30条数据到第40条记录数
    Sql Server 复制表
    Sql 常见面试题
    Sql Server 简单查询 异步服务器更新语句
    jQuery stop()用法以及案例展示
    CSS3打造不断旋转的CD封面
  • 原文地址:https://www.cnblogs.com/Sakits/p/7794578.html
Copyright © 2011-2022 走看看