B. Tolik and His Uncle(构造+特殊情况推导)

https://codeforces.com/problemset/problem/1179/B


题意翻译

有一天,_rqy想出来了一道构造题,出给了wqy去做。然而wqy不会做,于是就来找你。

你有一个nn行mm列的棋盘,其中第ii行第jj列的格子标号为(i,j)(i,j)。你需要从(1,1)(1,1)开始遍历这个棋盘。每一次,如果你在(x,y)(x,y),你可以选择一个向量(\text{d}x,\text{d}y)(dx,dy),并且移动到(x+\text{d}x,y+\text{d}y)(x+dx,y+dy)这个格子上。

你不能离开这个棋盘,同时每一个向量只能使用一次。你的任务是合理安排自己的行走路线,使得每一个格子都只被经过一次。输出这个方案。

wqy翻译了那么多题面,你一定要帮他解出来!


思路:从开始的1行多列去思考,会发现这是一个按照中心对称跳来跳去的。

对于两行的情况 2,3:

(1,1)->(2,3)->(1,2)->(2,2)->(1,3)->(2,1)

每两次移动为(1,n - i)和(-1,n - 1 - i)

然后类推,对于多行,找关于其中心对称点跳来跳去,这时候会有奇数行和偶数行,奇数行要最后在中间再加一个一行的中心对称跳来跳去的情况。

启示:矩阵构造题从一行/一列先找规律。记得暑假写的一道2800的构造题,也是这样推,每一行推过去取出构造规律。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5;
typedef long long LL;
int main(void)
{
  //cin.tie(0);std::ios::sync_with_stdio(false);
  int n,m;
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n/2;i++)
  {
  	for(int j=1;j<=m;j++)
  	{
  		printf("%d %d\n",i,j);
  		printf("%d %d\n",n-i+1,m-j+1); 
	}
  }
  if(n&1)
  {
  	n=(n+1)/2;
	for(int j=1;j<=m/2;j++)
	{
		printf("%d %d\n",n,j);
		printf("%d %d\n",n,m-j+1);
	}
	if(m&1) printf("%d %d",n,(m+1)/2);
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108626130