• SRM 552 DIV2


    250pt

    题意:

    给定二维格点图和一个在格点图中的禁止点,每个格点包含01,求最多有多少个1被包含在一个不包含在禁止点的矩形里。

     

    分析:

    以禁止点所在行,列为边界,枚举,共4种情况。

    View Code
    #include <cstdlib> 
    #include <cctype> 
    #include <cstring> 
    #include <cstdio> 
    #include <cmath> 
    #include <algorithm> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <sstream> 
    #include <map> 
    #include <set> 
    #include <queue> 
    #include <stack> 
    #include <fstream> 
    #include <iomanip> 
    #include <bitset> 
    #include <list> 
    using namespace std; 
    #define REP(i,n) for(i=0;i<(n);++i) 
    #define FOR(i,l,h) for(i=(l);i<=(h);++i) 
    #define FORD(i,h,l) for(i=(h);i>=(l);--i) 
    typedef vector<int> VI; 
    typedef vector<double> VD; 
    typedef long long LL; 
    
    class FoxAndFlowerShopDivTwo 
    { 
            public: 
            int theMaxFlowers(vector <string> f, int r, int c) 
            {
                int i,j,n,m,k,ret;
                n=(int)f.size();
                m=(int)f[0].size();
    
                k=ret=0;
                for(i=0;i<r;i++)
                    for(j=0;j<m;j++)
                        if(f[i][j]=='F')
                            k++;
                if(k>ret)
                    ret=k;
    
                k=0;
                for(i=r+1;i<n;i++)
                    for(j=0;j<m;j++)
                        if(f[i][j]=='F')
                            k++;
                if(k>ret)
                    ret=k;
    
                k=0;
                for(i=0;i<n;i++)
                    for(j=0;j<c;j++)
                        if(f[i][j]=='F')
                            k++;
                if(k>ret)
                    ret=k;
    
                k=0;
                for(i=0;i<n;i++)
                    for(j=c+1;j<m;j++)
                        if(f[i][j]=='F')
                            k++;
                if(k>ret)
                    ret=k;
                return ret;
            } 
            
     
    }; 

     

    500pt

    题意:

    定义一种n行三角球堆,第n行有n个球紧密排列,n-1行有n-1球堆在第nn个球的上方的缝隙,依此类推,所以总共有(n*(n+1))/2个球。现有三种颜色给球堆着色,相邻的小球颜色不能相同。给定三种颜色的数量,求能给多少个n行三角堆完全着色。

     

    分析:

    观察易得,

    n%3=23时,红,绿,蓝所用颜色数相同,min(R,G,B)/(n*(n+1)/6);

    n%3=1时,有一种颜色比其余两种颜色多一次,可用二分搜索解决。

    View Code
    #include <cstdlib> 
    #include <cctype> 
    #include <cstring> 
    #include <cstdio> 
    #include <cmath> 
    #include <algorithm> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <sstream> 
    #include <map> 
    #include <set> 
    #include <queue> 
    #include <stack> 
    #include <fstream> 
    #include <iomanip> 
    #include <bitset> 
    #include <list> 
    using namespace std; 
    #define REP(i,n) for(i=0;i<(n);++i) 
    #define FOR(i,l,h) for(i=(l);i<=(h);++i) 
    #define FORD(i,h,l) for(i=(h);i>=(l);--i) 
    typedef vector<int> VI; 
    typedef vector<double> VD; 
    typedef long long LL; 
    
    class FoxPaintingBalls 
    { 
            public: 
            long long theMax(long long R, long long G, long long B, int N) 
            { 
                    LL i,j,k,m,ret=0;
                    LL s=(LL)N*(N+1)/6;
                    if(N==1)
                        return R+G+B ;
                    k=min(R,min(G,B));
                    if(N%3==0||N%3==2)
                        return k/s;
                    for(i=1,j=k/s;i<=j;)
                    {
                        m=(i+j)>>1;
                        if(k>=m*s&&R+G+B-m*s*3>=m)
                        {
                            ret=m;
                            i=m+1;
                        }
                        else
                            j=m-1;
                    }
                    return ret;
            } 
            
    
     
    }; 

    1000pt

    题意:

    给定一个数组F[],nK,满足for all i, 0<=i<KA[i]=F[i]otherwiseA[i]=A[i-K]-A[i-K+1]+....+(-1)^(K-1)*A[i-1]。调整F[]的排列顺序可更改A[]的值。

    求使A[n]最大的F[]排列

     

    分析:

    易得,一定存在一个C[]使得A[N]=C[0]*F[0]+C[1]*F[1]...+C[K-1]*F[K-1],所以只要求出C[],或者求出C[]的相对大小关系就可以求出解。

     

    1K是奇数时:

    A[i]=A[i-K]-A[i-k+1].....-A[i-1]

    A[i-1]=A[i-K-1]-A[i-K]...-A[i-2]

    两式相加,A[i]+A[i-1]=A[i-K-1]-A[i-1],

    A[i]=A[i-K-1],即当K是奇数时,A[n]=A[n%(K+1)],其余排列字典序最小。

     

    2K是偶数时:

    同理可推,A[i]=A[i-K-1]-2*A[i-1],一下子看不出来,找规律。

    i

    C[0]

    C[1]

    C[2]

    C[3]

    ...

    C[K-1]

    K

    -1

    1

    -1

    1

    ...

    1

    K+1

    -1

    2

    -2

    2

     

    2

    K+2

    -2

    -3

    4

    -4

     

    -4

    K+3

    -4

    6

    -7

    8

     

    8

    观察可得,i是奇数,奇数项全为负,单调递减,偶数全为正,单调递增,i是偶数则相反。由此可确定C[]的相对大小关系。

     

    View Code
    #include <cstdlib> 
    #include <cctype> 
    #include <cstring> 
    #include <cstdio> 
    #include <cmath> 
    #include <algorithm> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <sstream> 
    #include <map> 
    #include <set> 
    #include <queue> 
    #include <stack> 
    #include <fstream> 
    #include <iomanip> 
    #include <bitset> 
    #include <list> 
    using namespace std; 
    #define REP(i,n) for(i=0;i<(n);++i) 
    #define FOR(i,l,h) for(i=(l);i<=(h);++i) 
    #define FORD(i,h,l) for(i=(h);i>=(l);--i) 
    typedef vector<int> VI; 
    typedef vector<double> VD; 
    typedef long long LL; 
    
    class FoxPlusMinus 
    { 
            public: 
            vector <int> call(vector <int> C, vector <int> a)
            {
                VI ret;
                int i,j,k,n=a.size();
                sort(a.begin(),a.end());
                for(i=0;i<n;i++)
                {
                    for(j=k=0;j<n;j++)
                        if(i!=j)
                        {
                            if(C[j]<C[i]||(C[j]==C[i]&&j<i))
                                k++;
                        }
                    ret.push_back(a[k]);
                }
                return ret;
            }
            vector <int> maximize(vector <int> first, int N) 
            {
                int i,j,K=first.size();
                VI C;
                for(i=0;i<K;i++)
                    C.push_back(0);
                if(K&1)
                {
                    if(N%(K+1)==K)
                    {
                        for(i=0;i<K;i++)
                            if(i&1)
                                C[i]=-1;
                            else
                                C[i]=1;
                    }
                    else
                        C[N%(K+1)]=1;
                    //printf("K&1    ");
                    return call(C,first);
                }
                if(N<K)
                {
                    C[N]=1;
                    //printf("N<K    ");
                    return call(C,first);
                }
    
                if(N&1)
                {
                    for(i=0;i<K;i++)
                        if(i&1) C[i]=i+1;
                        else C[i]=-i-1;
                }
                else
                {
                    for(i=0;i<K;i++)
                        if(i&1) C[i]=-i-1;
                        else C[i]=i+1;
                }
    
                if(N<2*K)
                {
                    for(i=N-K+1;i<K;i++)
                        C[i]=-C[i-1];
                }
                return call(C,first);
    
    
            } 
            
    
     
    }; 

     

     

  • 相关阅读:
    linux基础学习2
    linux下部署项目问题
    ThinkPHP上传返回 “文件上传保存错误!”
    jQuery自定义插件
    对于nginx为什么能提高性能
    WebSocket 是什么原理?为什么可以实现持久连接?
    数据库的左右外连接
    漫画说算法--动态规划算法一(绝对通俗易懂,非常棒)
    Integer.MIN_VALUE
    反射
  • 原文地址:https://www.cnblogs.com/xchaos/p/2684597.html
Copyright © 2020-2023  润新知