zoukankan      html  css  js  c++  java
  • timus1965(不错的贪心)

    题意是:给你一个1-n的排列,要你把这个排列分成两个序列,且这个两个序列都满足单调性。

    题解:

    1.首先假设找出的两个序列都是单调递增的(都是单调递减的同理)

    那么很容易可以想到,将新加入的数放入到某个序列尾端,使得另一个序列尾端的数尽量小。

    2.如果最后的两个序列为一个递增一个递减。

    这种情况下,有一种眼光稍微长远一些的贪心策略。

    假设当前要加入的数g[x],如果g[x]既可以放入单增序列中也可以放入单减序列中,则与g[x+1]比较。

    if(g[x]>g[x+1]) 把g[x]放入单减序列中

    else 把g[x]放入单增序列中

    为什么这样贪心就行了?

    可以做一个假设,当g[x]>g[x+1],我们却把g[x]放入单增序列中,则g[x]只能放入单减序列,最后得出的两个序列的尾部为:

    xxxxg[x]    (单增序列)        。。。。。。。。。方法一

    xxxxxxg[x+1] (单减序列)

    而当我们把g[x]放入单减序列时,此时g[x+1]可能放入单增序列中,一定可以放入单减序列中,

    1.如果g[x+1] 放入单减序列中,得出两个序列尾部为:

    xxxX        (单增序列)    。。。。。。。。。方法二

    xxxxxxg[x]g[x+1]  (单减序列)

    而X<g[x] ,所以下面这种方法得出的结果一定优于方法一。

    2.如果g[x+1]能放入单增序列,放入其中得出的两个序列尾部为:

    xxxxg[x+1]  (单增序列)        。。。。。。。。。方法三

    xxxxxxg[x]  (单减序列)

    因为g[x]>g[x+1],所以结果一定优于方法一。

    把眼界放开,即使是贪心也能贪的漂亮!

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxN 100005
    const int inf=~0U>>1;
    int s1[maxN];
    int f[maxN][2];
    int N,len1,len2;
    bool judge1()
    {
        f[0][0]=f[0][1]=-1;
        len1=len2=0;
        for(int i=1;i<=N;i++)
        {
            if(s1[i]<f[len1][0]&&s1[i]<f[len2][1])
                return false;
            else if(s1[i]>f[len1][0]&&s1[i]<f[len2][1])
                f[++len1][0]=s1[i];
            else if(s1[i]<f[len1][0]&&s1[i]>f[len2][1])
                f[++len2][1]=s1[i];
            else
            {
                if(f[len2][1]>f[len1][0]) f[++len2][1]=s1[i];
                else f[++len1][0]=s1[i];
            }
        }
        if(len1==N) f[++len2][1]=f[len1--][0];
        return true;
    }
    bool judge2()
    {
        f[0][0]=f[0][1]=inf;
        len1=len2=0;
        for(int i=1;i<=N;i++)
        {
            if(s1[i]>f[len1][0]&&s1[i]>f[len2][1])
                return false;
            else if(s1[i]>f[len1][0]&&s1[i]<f[len2][1])
                f[++len2][1]=s1[i];
            else if(s1[i]<f[len1][0]&&s1[i]>f[len2][1])
                f[++len1][0]=s1[i];
            else
            {
                if(f[len2][1]<f[len1][0]) f[++len2][1]=s1[i];
                else f[++len1][0]=s1[i];
            }
        }
        if(len1==N) f[++len2][1]=f[len1--][0];
        return true;
    }
    bool judge3()
    {
        len1 = len2 = 0;
        f[len1][0]=-1;
        f[len2][1]=inf;
        for(int i=1;i<=N;i++)
        {
            if(s1[i]<f[len1][0]&&s1[i]>f[len2][1]) return false;
            else if(s1[i]>f[len1][0]&&s1[i]<f[len2][1])
            {
                if(i==N) f[++len1][0]=s1[i];
                else if(s1[i+1]>s1[i]) f[++len1][0]=s1[i];
                else f[++len2][1]=s1[i];
            }
            else if(s1[i]>f[len1][0])
                f[++len1][0]=s1[i];
            else
                f[++len2][1]=s1[i];
        }
        return true;
    }
    int main()
    {
        scanf("%d",&N);
        for(int i=1,j=N;i<=N;i++,j--)
        {
            scanf("%d",&s1[i]);
        }
        if(judge1())
        {
            printf("%d %d
    ",len1,len2);
            for(int i=1;i<=len1;i++) printf("%d%c",f[i][0],i==len1?'
    ':' ');
            for(int i=1;i<=len2;i++) printf("%d%c",f[i][1],i==len2?'
    ':' ');
            return 0;
        }
        if(judge2())
        {
            printf("%d %d
    ",len1,len2);
            for(int i=1;i<=len1;i++) printf("%d%c",f[i][0],i==len1?'
    ':' ');
            for(int i=1;i<=len2;i++) printf("%d%c",f[i][1],i==len2?'
    ':' ');
            return 0;
        }
        if(judge3())
        {
            printf("%d %d
    ",len1,len2);
            for(int i=1;i<=len1;i++) printf("%d%c",f[i][0],i==len1?'
    ':' ');
            for(int i=1;i<=len2;i++) printf("%d%c",f[i][1],i==len2?'
    ':' ');
            return 0;
        }
        printf("Fail
    ");
        //print1(dp1[len1]);
        //printf("
    ");
        //print2(dp2[len2]);
        return 0;
    }

    另加一个,我自己想的丑陋的贪心。。。

    //
    //  main.cpp
    //  timus1965
    //
    //  Created by 陈加寿 on 16/3/16.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <set>
    #include <math.h>
    #include <algorithm>
    using namespace std;
    #define N 100100
    
    int g[N],tg[N];
    int ans1[N],ans2[N];
    int cnt1,cnt2;
    int n;
    int b1,d1,b2,d2;
    
    int fuc()
    {
        cnt1 = cnt2 =0;
        //->
        ans2[0] = 0;
        ans1[ ++cnt1 ] = g[1];
        for(int i=2;i<=n;i++)
        {
            if(g[i]<ans1[cnt1] && g[i]<ans2[cnt2])
            {
                return 0;
            }
            //否则选尽量大的一边
            if(g[i]>ans1[cnt1]) ans1[++cnt1]=g[i];
            else ans2[++cnt2]=g[i];
        }
        return 1;
    }
    
    int fuc1()
    {
        cnt1 = cnt2 =0;
        //<-
        ans2[0] = n+1;
        ans1[ ++cnt1 ] = g[1];
        for(int i=2;i<=n;i++)
        {
            if(g[i]>ans1[cnt1] && g[i]>ans2[cnt2])
            {
                return 0;
            }
            //否则选尽量小的一边
            if(g[i]<ans1[cnt1]) ans1[++cnt1]=g[i];
            else ans2[++cnt2]=g[i];
        }
        return 1;
    }
    
    int test1(int b,int d)
    {
        if( tg[d]<b1 || tg[d]>d1 ) return 0;// g[i]无法放入ans1中
        //把(b,d)间的数全部放入ans2中去
        //首先保证(b,d)之间是递减的
        if(b+1 == d)
        {
            ans1[++cnt1] = d;
            b1 = tg[d];
            return 1;
        }
        for(int i=d-2;i>b;i--)
        {
            if(tg[i]<tg[i+1]) return 0;//并不递减
        }
        if( tg[d-1]>b2 && tg[b+1]<d2 )
        {
            for(int i=d-1;i>b;i--)
                ans2[++cnt2] = i;
            ans1[++cnt1] = d;
            d2=tg[d-1];
            b1 = tg[d];
            return 1;
        }
        else return 0;
    }
    
    int test2(int b,int d)
    {
        if(tg[b]<b2 || tg[b]>d2) return 0;
        if(b+1 == d)
        {
            ans2[++cnt2] = b;
            b2 = tg[b];
            return 1;
        }
        for(int i=b+1;i<d-1;i++)
        {
            if(tg[i]>tg[i+1]) return 0;
        }
        if(tg[b+1]>b1 && tg[d-1]<d1)
        {
            for(int i=d-1;i>b;i--)
                ans1[++cnt1] = i;
            ans2[++cnt2] = b;
            d1 = tg[b+1];
            b2 = tg[b];
            return 1;
        }
        else return 0;
    }
    
    int solve()
    {
        int b=0,d=n+1;
        b1=0,d1=n+1;
        b2=0,d2=n+1;
        //并不需要set
        for(int i=1;i<=n;i++)
        {
            if( g[i]<b || g[i]>d) continue; //已经处理过的,不再处理
            if(g[i]-b < d-g[i])
            {
                //靠左,g[i]放入ans1中
                if( test1(b,g[i])==1 )
                {
                    //如果
                    b = g[i];
                }
                else if(test2(g[i],d)==1)
                {
                    d = g[i];
                }
                else return 0;//两个测试都不过 直接返回不行.
            }
            else
            {
                //靠右
                if(test2(g[i],d)==1)
                {
                    d=g[i];
                }
                else if(test1(b, g[i])==1)
                {
                    b=g[i];
                }
                else return 0;
            }
        }
        return 1;
    }
    
    int cmp(int x,int y)
    {
        return x>y;
    }
    
    int main() {
        cin>>n;
        
        for(int i=1;i<=n;i++)
        {
            scanf("%d",g+i);
            tg[ g[i] ] = i;
        }
        g[0]=0; g[n+1]=n+1;
        tg[0]=0; tg[n+1]=n+1;
        cnt1 = cnt2 = 0;
        int flag=0;
        //step one  tha same direction
        if( fuc() || fuc1() )
        {
            flag=1;
        }
        if(flag == 0)
        {
            // step two the different direction
            cnt1 = cnt2 =0;
            flag = solve();
            //最后再sort一下
            sort(ans1+1,ans1+1+cnt1);
            sort(ans2+1,ans2+1+cnt2,cmp);
        }
        if(flag == 0)
        {
            printf("Fail
    ");
        }
        else
        {
            //输出答案
            if(cnt1==n)
            {
                ans2[++cnt2] = ans1[cnt1--];
            }
            if(cnt2==n)
            {
                ans1[++cnt1] = ans2[cnt2--];
            }
            cout<<cnt1<<" "<<cnt2<<endl;
            for(int i=1;i<=cnt1;i++) printf("%d ",ans1[i]);
            printf("
    ");
            for(int i=1;i<=cnt2;i++) printf("%d ",ans2[i]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    keras与卷积神经网络(CNN)实现识别mnist手写数字
    Pytorch自动求解梯度
    Kaggle竞赛入门(四):随机森林算法的Python实现
    Kaggle竞赛入门(三):用Python处理过拟合和欠拟合,得到最佳模型
    Kaggle竞赛入门(二):如何验证机器学习模型
    Kaggle竞赛入门(一):决策树算法的Python实现
    R语言入门:正态分布中dnorm(),pnorm(),qnorm(),和rnorm()函数的使用
    初识suse-Linux相关!
    关于visio 2007导入独立图库
    让windows 2003启动后直接进入桌面
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5289887.html
Copyright © 2011-2022 走看看