zoukankan      html  css  js  c++  java
  • nowcoder 211B

    题目链接:https://www.nowcoder.com/acm/contest/211/B

    题目描述
    炎热的早上,gal男神们被迫再操场上列队,gal男神们本来想排列成x∗x的正方形,可是因为操场太小了(也可能是gal男神太大了),校长安排gal男神们站成多个4∗4的正方形(gal男神们可以正好分成n个正方形)但是有些gal男神对于这种站法颇有微词,所以他们把衣服脱下来拿在手上摇晃示威,站在一条直线上的gal男神可以“交头接耳”,交头接耳会使他们联合起来闹事,人数越多,威胁程度就越大。你作为也反对这种站队方式的体育老师,为了助纣为虐,应该以一种“合理”的方式来排布n个gal男神方阵,使得最大的威胁程度最大。输出这个威胁程度。
    以下为化简版题干:
    现在有n个由0和1组成的4∗4矩阵,你可以任意排列这些矩阵(注意:你不能旋转或者翻转它们),但是每两个矩阵应该恰好对应。即第一列对第一列(或是第一行对第一行)比如说:
    聪明的你一定可以找到一种排列方法使“连续1的序列最长”。我们定义“连续的1序列”为这个序列仅含1且这个序列不拐弯,它可以是横着或者竖着的。请输出最长的“连续的1序列”长度
    输入描述:
    第一行一个n。
    接下来 4*n行,每行4个数。(仅含0,1)。代表n个0/1矩阵。
    输出描述:
    一个数字表示最长的“连续的1序列”的长度。
    示例1
    输入
    1
    1 1 1 1
    1 1 1 1
    1 1 1 1
    1 1 1 1
    输出
    4
    示例2
    输入
    1
    0 0 0 0
    0 0 0 0
    0 0 0 0
    0 0 0 0
    输出
    0
    示例3
    输入
    3
    1 0 1 0
    0 0 1 0
    1 0 1 0
    0 1 0 1

    1 0 1 0
    0 1 1 1
    1 0 1 1
    1 1 1 0

    1 0 1 1
    0 1 0 0
    0 1 0 0
    0 0 0 1
    输出
    7
    备注:
    对于前30%,保证n<=1e3.( 然而并没卵用 )
    对于前100%的数据,保证n<=1e5.
    乱搞是没有活路的,出题人在验题时已经卡掉9种奇奇怪怪的dp和贪心了。
    包括但不限于区间dp,O(n)的错误dp,模拟退火算法,爬山算法,遗传算法等.
    而且出题人特别卡掉了快读。
    ps:10%的数据保证随机。

    题解:

    对四行四列分别统计,每一行(列)下的每一个矩阵都有三种情况:

      1、四个 $1$ 全满;这个直接计数为 $fullcnt$。

      2、不是四个 $1$,但是左起(上起)或者右起(下起)能至少有一个 $1$;左起(上起)的放一起统计,右起(下起)的放一起统计。

      3、两侧都是 $0$,那么此时只有中间一个或者两个 $1$,这个再单独统计。

    那么,对于某一行(某一列),他能产生的最长连续 $1$ 的长度为:

      1、四个 $1$ 全满的计数 $fullcnt$ 产生贡献 $4 imes fullcnt$。

      2、左起(上起)中最长的,加上,右起(下起)中最长的,即产生的贡献(当然,如果两个最长的同属于一个矩阵,则要考虑在“左起最长+右起次长”和“右起最长+左起次长”中挑一个)。

      3、两侧都是 $0$,显然上面两种情况的贡献就均为 $0$,而本情况能产生 $2$ 或 $3$ 的贡献。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    
    int n;
    struct Mat
    {
        int mp[5][5];
        int cnt[2][5][2];
        void input()
        {
            for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) scanf("%d",&mp[i][j]);
            for(int i=1;i<=4;i++)
            {
                cnt[0][i][0]=0;
                for(int j=1;j<=4;j++)
                {
                    if(mp[i][j]) cnt[0][i][0]++;
                    else break;
                }//printf("第%d行左边起%d
    ",i,cnt[0][i][0]);
                cnt[0][i][1]=0;
                for(int j=4;j>=1;j--)
                {
                    if(mp[i][j]) cnt[0][i][1]++;
                    else break;
                }//printf("第%d行右边起%d
    ",i,cnt[0][i][1]);
            }
            for(int j=1;j<=4;j++)
            {
                cnt[1][j][0]=0;
                for(int i=1;i<=4;i++)
                {
                    if(mp[i][j]) cnt[1][j][0]++;
                    else break;
                }//printf("第%d列上边起%d
    ",j,cnt[1][j][0]);
                cnt[1][j][1]=0;
                for(int i=4;i>=1;i--)
                {
                    if(mp[i][j]) cnt[1][j][1]++;
                    else break;
                }//printf("第%d列下边起%d
    ",j,cnt[1][j][1]);
            }
        }
    }mat[maxn];
    
    struct Node
    {
        int val;
        int id;
        bool operator<(const Node& oth)const{return val>oth.val;}
        Node(int _val,int _id){val=_val;id=_id;}
    };
    vector<Node> v[2][5][2],u[2][5];
    int fullcnt[2][5]={0};
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            mat[i].input();
            for(int rc=0;rc<=1;rc++)
            {
                for(int k=1;k<=4;k++)
                {
                    if(mat[i].cnt[rc][k][0]==4 || mat[i].cnt[rc][k][1]==4) //全满,type=2
                        fullcnt[rc][k]++;
                    else if(mat[i].cnt[rc][k][0]>0) //左侧或上侧,type=3
                        v[rc][k][0].push_back(Node(mat[i].cnt[rc][k][0],i));
                    else if(mat[i].cnt[rc][k][1]>0) //右侧或下侧,type=1
                        v[rc][k][1].push_back(Node(mat[i].cnt[rc][k][1],i));
                    else //只存在于内部,type=4
                    {
                        int num=(!rc)?(mat[i].mp[k][2]+mat[i].mp[k][3]):(mat[i].mp[2][k]+mat[i].mp[3][k]);
                        u[rc][k].push_back(Node(num,i));
                    }
                }
            }
        }
        int ans=0;
        for(int rc=0;rc<=1;rc++)
        {
            for(int k=1;k<=4;k++)
            {
                sort(v[rc][k][0].begin(),v[rc][k][0].end());
                sort(v[rc][k][1].begin(),v[rc][k][1].end());
                int res;
                if(v[rc][k][0].size() && v[rc][k][1].size())
                {
                    Node& m1=v[rc][k][0][0],m2=v[rc][k][0][1];
                    Node& n1=v[rc][k][1][0],n2=v[rc][k][1][1];
                    res=(m1.id!=n1.id)?(m1.val+n1.val):max(m1.val+n2.val,m2.val+n1.val);
                }
                else if(v[rc][k][0].size() || v[rc][k][1].size())
                {
                    if(v[rc][k][0].size()) res=v[rc][k][0][0].val;
                    else res=v[rc][k][1][0].val;
                }
                else
                {
                    if(u[rc][k].size())
                    {
                        sort(u[rc][k].begin(),u[rc][k].end());
                        res=u[rc][k][0].val;
                    }
                    else res=0;
                }
                ans=max(ans,4*fullcnt[rc][k]+res);
            }
        }
        cout<<ans<<endl;
    }

    给一些测试数据:

    1
    0 0 0 0
    0 1 1 0
    0 1 0 0
    0 0 0 0
    1
    0 0 0 0
    0 1 0 0
    0 1 0 0
    0 0 0 0
    1
    0 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 0
    1
    1 1 1 0
    0 0 0 0
    0 1 1 1
    1 0 0 0
    1
    0 0 0 0
    0 0 1 0
    0 1 0 0
    0 0 0 0
    0 0 0 0
    0 0 0 0
    0 1 1 0
    0 0 0 0
  • 相关阅读:
    001-Java®语言规范、Java平台标准版文档、JVM概述
    004-RIP、OSPF【路由选择协议】
    003-ARP地址解析协议
    0405-服务注册与发现-客户端负载均衡-Ribbon 同Eureka使用,Ribbon脱离Eureka使用
    0404-服务注册与发现-客户端负载均衡-两种自定义方式-Ribbon通过代码自定义配置、使用配置文件自定义Ribbon Client
    网页嵌入swf代码
    解决html5 video不能播放 能播放声音不能播放视频
    代码高亮插件SyntaxHighlighter
    透明度
    web图片轮播实现
  • 原文地址:https://www.cnblogs.com/dilthey/p/9821968.html
Copyright © 2011-2022 走看看