【JSCPC】2021江苏省赛 D. Pattern Lock | 结构

标题链接

Problem – D – Codeforces

标题

【JSCPC】2021江苏省赛 D. Pattern Lock | 构造

标题大意

nnmm 列的点阵图,要求结构 nmn\times m 个整点的摆放,摆放中恣意相邻两个点构成一条线段,满足以下条件:

  • 任一线段不通过除端点外的其他整点。
  • 相邻两条线段形成的角是锐角。

数据规模:2≤n,m≤5002 ≤ n, m ≤ 500

思路

有多种解法,下面给出一种合法的结构办法:

【JSCPC】2021江苏省赛 D. Pattern Lock | 构造

整体思想为尽量走 Z 字,每相邻两个点的横坐标或纵坐标相差 11 即可确保不每个线段不通过其他点。

蓝色部分

假如 nn 为偶数,咱们能够每两行为一组进行结构。

具体完成如下:

//从第 u 行到第 d 行,第 l 列到第 r 列用蓝色办法进行掩盖
void solven(int u,int d,int l,int r)
{
	for (int i=u,t=0;i<=d;i+=2,t=!t)
	{
		if (t&1)
		{
			for (int j=r;j>l;--j) ans.push_back({i,j}),ans.push_back({i+1,j-1});
			ans.push_back({i,l});
			ans.push_back({i+1,r});
		}
		else
		{
			for (int j=l;j<r;++j) ans.push_back({i,j}),ans.push_back({i+1,j+1});
			ans.push_back({i,r});
			ans.push_back({i+1,l});
		}
	}
}

这里有一种特殊状况,若 nn 为偶数但不等于 22,且 m=2m=2 时,用这种办法掩盖会呈现直角,所以进行讨论时这种状况转到黄色部分的结构办法。

【JSCPC】2021江苏省赛 D. Pattern Lock | 构造

黄色部分

假如 mm 为偶数,咱们能够每两列为一组进行结构,具体完成与蓝色部分相似,详见代码不再赘述。相同的,若 mm 为偶数但不等于 22,且 n=2n=2 时,用黄色部分的结构办法会呈现直角,所以在这种状况下应该使用蓝色结构办法。

赤色部分

nnmm 均为奇数时,咱们从左上角取出一个 333\times 3 的矩阵直接手玩出答案,就能够把剩下的部分划分红两个有偶数边长的矩阵。

赤色部分为手玩出来的固定解法,直接按图片将点顺次参加答案即可。

ans.push_back({1,3});
ans.push_back({3,2});
ans.push_back({1,1});
ans.push_back({2,3});
ans.push_back({3,1});
ans.push_back({1,2});
ans.push_back({3,3});
ans.push_back({2,1});
ans.push_back({2,2});

离开赤色部分能够直接用黄色部分的结构办法掩盖右侧的 n(m−3)n\times (m-3) 的点阵,但是从赤色部分直接转向蓝色部分会呈现钝角,于是用绿色部分进行衔接。

绿色部分

nnmm 均为奇数且 n>3n>3 时,咱们需要用蓝色的结构办法掩盖一个 (n−3)m(n-3)\times m 的矩阵,但是从 (2,2)(2,2) 点出发直接转为蓝色结构办法会呈现钝角,于是用绿色结构办法进行衔接。

该部分也是手玩出来的……相同按图顺次参加答案。

ans.push_back({4,1});
ans.push_back({4,2});
ans.push_back({5,1});
ans.push_back({4,3});
ans.push_back({5,2});
ans.push_back({5,3});

代码

#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
struct asdf{
	int x,y;
};
vector<asdf> ans;
int n,m;
void solven(int u,int d,int l,int r)
{
	for (int i=u,t=0;i<=d;i+=2,t=!t)
	{
		if (t&1)
		{
			for (int j=r;j>l;--j) ans.push_back({i,j}),ans.push_back({i+1,j-1});
			ans.push_back({i,l});
			ans.push_back({i+1,r});
		}
		else
		{
			for (int j=l;j<r;++j) ans.push_back({i,j}),ans.push_back({i+1,j+1});
			ans.push_back({i,r});
			ans.push_back({i+1,l});
		}
	}
}
void solvem(int u,int d,int l,int r)
{
	for (int i=r,t=((r-l+1)/2)%2;i>=l;i-=2,t=!t)
	{
		if (t&1)
		{
			ans.push_back({d,i});
			ans.push_back({u,i-1});
			for (int j=u;j<d;++j) ans.push_back({j,i}),ans.push_back({j+1,i-1});
		}
		else
		{
			ans.push_back({u,i});
			ans.push_back({d,i-1});
			for (int j=d;j>u;--j) ans.push_back({j,i}),ans.push_back({j-1,i-1});
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	if (n%2==0&&m!=2) solven(1,n,1,m);
	else if (m%2==0) solvem(1,n,1,m);
	else
	{
		solvem(1,n,4,m);
		ans.push_back({1,3});
		ans.push_back({3,2});
		ans.push_back({1,1});
		ans.push_back({2,3});
		ans.push_back({3,1});
		ans.push_back({1,2});
		ans.push_back({3,3});
		ans.push_back({2,1});
		ans.push_back({2,2});
		if (n>3)
		{
			ans.push_back({4,1});
			ans.push_back({4,2});
			ans.push_back({5,1});
			ans.push_back({4,3});
			ans.push_back({5,2});
			ans.push_back({5,3});
		}
		solven(6,n,1,3);
	}
	for (auto v:ans) printf("%d %d\n",v.x,v.y);
	return 0;
}