2018青岛ICPC && ZOJ 4063: Tournament(构造)

 

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4063

 

题意:

给你n和k,都小于1000,构造一个k*n的数组满足

  1. 如果a[p][x]=y,那么a[p][y]必须等于x,1≤p≤k,1≤x,y≤n
  2. 每一列所有数字都必须不相同,每一行所有数字也都必须不相同,且都在[1,n]范围内
  3. 对于任意两行i, j,如果a[i][x] = y, a[i][y] = x,  a[i][c] = d,a[i][d] = c,且a[j][x] = c,a[j][c] = x,那么必须满足a[j][y] = d,且a[j][d] = y
  4. 字典序最小

构造不出来输出Impossible

 

思路:

构造题嘛,理论上不停拿数据测AC代码看输出就会做了,因为重要的是怎么构造

这题可以预处理1024*1024的情况,然后对于每次询问n, k,如果可以直接输出前n行前k列就可以了

 

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define LL long long
#define mod 1000000007
int len, ans[1038][1038];
void Gao(int x, int y, int n, int p)
{
	int i, j;
	if(n==1)
	{
		ans[x][y] = p;
		return;
	}
	n /= 2;
	Gao(x, y, n, p);
	Gao(x, y+n, n, p+n);
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			ans[x-1+i+n][y-1+j] = ans[x-1+i][y-1+j+n];
			ans[x-1+i+n][y-1+j+n] = ans[x-1+i][y-1+j];
		}
	}
}
int main(void)
{
	int T, n, k, i, j;
	Gao(1, 1, 1024, 1);
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d", &n, &k);
		if(k>=(n&-n))
			printf("Impossible\n");
		else
		{
			len = n;
			for(i=2;i<=k+1;i++)
			{
				printf("%d", ans[i][1]);
				for(j=2;j<=n;j++)
					printf(" %d", ans[i][j]);
				puts("");
			}
		}
	}
	return 0;
}

 

你可能感兴趣的:(构造)