CodeForces - 125C Hobbits' Party(思维+构造)

题目链接:点击查看

题目大意:有一个派对,现在有 n 个人参加,题目要求我们构造出一种参加方式,满足条件且可以维持的天数最大:

  1. 任意两天中至少有一个相同的人参加
  2. 任意三天中不能有一个相同的人参加

输出最大天数并给出构造方案

题目分析:一开始我想让相邻两个人互相在相邻的天数中出现,比如

1 n

1 2

2 3

...

n-1 n

n 1

但是发现这样的话第一个人会出现三次,与条件二不符,然后就想不出比较好的构造方案了,看了网上的题解后,虽然知道该怎么构造了,但还是不知道是如何思考的,稍微说一下吧:

假设当前的最大天数 m = 4 ,那么我们需要构造如下矩阵:

1 2 3 4

1 5 6 7

2 5 8 9

3 6 8 10 

4 7 9 10

可能看完后有点懵,下面我一步一步来解释为什么这样构造

首先第一行我们直接排列,以及第一列如下排列

1 2 3 4

1

2

3

4

这样一来就满足了第一行和其他任意一行满足条件了,接下来我们考虑第二行

1 2 3 4

1 5 6 7

2 5

3 6

4 7

这样第二行与其他的每一行也满足条件了,如此构造下去,我们最终会得到一个 m * ( m - 1 ) 的矩阵,构造起来也比较简单,沿着对角线分成两个部分,然后分别构造就是答案了,至于这个 m ,我们用一个while循环找就可以了,因为矩阵中一共有 2 * n 个元素,只要满足 m * ( m - 1 ) <= 2 * n,找到最大值就行了

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#include<unordered_map>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;
 
const int N=210;

int ans[N][N];

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	int n,m=0;
	scanf("%d",&n);
	while(m*(m+1)<=2*n)
		m++;
	int cnt1=0,cnt2=0;
	for(int i=1;i<=m-1;i++)
		for(int j=i;j<=m-1;j++)
			ans[i][j]=++cnt1;
	for(int j=1;j<=m-1;j++)
		for(int i=j+1;i<=m;i++)
			ans[i][j]=++cnt2;
	printf("%d\n",m);
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m-1;j++)
			printf("%d ",ans[i][j]);
		printf("\n");
	}
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}
发布了549 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104075960