列表

详情


NC19843. 列队

描述

炎热的早上,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

说明:

良心样例1

示例2

输入:

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

输出:

0

说明:

良心样例2

示例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

说明:

这回是真良心数据

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 179ms, 内存消耗: 7652K, 提交时间: 2018-10-19 20:33:41

#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN=1e5+5;
struct node
{
	int a[4][4];
	void input()
	{
		for(int i=0;i<4;i++)
		{
			for(int j=0;j<4;j++)
			{
				scanf("%d",&a[i][j]);
			}
		}
	}
	void trans()
	{
		for(int i=0;i<4;i++)
		{
			for(int j=i+1;j<4;j++)
			{
				swap(a[i][j],a[j][i]);
			}
		}
	}
}sv[MAXN];
int n,ans=0;
int l[MAXN],r[MAXN];
void solve()
{
	for(int i=0;i<4;i++)
	{
		int tot=0;//4
		int sum=0,mxl=0,mxr=0;
		memset(l,0,sizeof(l));
		memset(r,0,sizeof(r));
		for(int k=1;k<=n;k++)
		{
			for(int j=0;j<4;j++)
			{
				if(sv[k].a[i][j])
					l[k]++;
				else
					break;
			}
			for(int j=3;j>=0;j--)
			{
				if(sv[k].a[i][j])
					r[k]++;
				else
					break;
			}
			int cnt=0;
			for(int j=0;j<4;j++)
			{
				if(sv[k].a[i][j])
					cnt++;
				else
					cnt=0;
				ans=max(cnt,ans);
			}
			if(l[k]==4) tot++;
		}
		for(int k=1;k<=n;k++)
		{
            if(l[k]==4) continue;
			sum=max(sum,max(mxl+r[k],mxr+l[k]));
			mxl=max(mxl,l[k]);mxr=max(mxr,r[k]);
		}
		ans=max(ans,tot*4+sum);
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		sv[i].input();
	solve();
	for(int i=1;i<=n;i++)
		sv[i].trans();
	solve();
	printf("%d\n",ans);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 152ms, 内存消耗: 604K, 提交时间: 2020-02-27 19:12:47

#include<bits/stdc++.h>
using namespace std;
int n,i,j,k,a[4][4],ans,s[8][16],o[16],o1[16],o2[16];
void fix(int x,int y)
{
	s[x][y]++;
}
int main()
{
	for(i=0;i<16;i++)
	for(i=0;i<16;i++)
	{
		o[i]=o[i>>1];
		if(i&1) o[i]=max(o[i],o1[i]=o1[i>>1]+1);
	}
	for(i=0;i<16;i++)
	{
		for(j=3;~j;j--)
		if(!(i>>j&1)) break;
		o2[i]=3-j;
	}
	scanf("%d",&n);
	while(n--)
	{
		for(i=0;i<4;i++)
		for(j=0;j<4;j++)
		scanf("%d",a[i]+j);
		for(i=0;i<4;i++)
		{
			for(j=k=0;j<4;j++) k=k<<1|a[i][j];
			fix(i,k);
			for(j=k=0;j<4;j++) k=k<<1|a[j][i];
			fix(i+4,k);
		}
	}
	for(i=0;i<8;i++)
	for(ans=max(ans,4*s[i][15]),j=0;j<15;j++)
	if(s[i][j])
	{
		ans=max(ans,max(o[j],max(o1[j],o2[j])+4*s[i][15]));
		for(k=0;k<15;k++)
		if(s[i][k]>(k==j))
		ans=max(ans,o1[j]+o2[k]+4*s[i][15]);
	}
	cout<<ans<<endl;
	return 0;
}

上一题