Codeforces 906B. Seating of Students(构造+DFS)

时间:2023-03-09 23:09:17
Codeforces 906B. Seating of Students(构造+DFS)

  行和列>4的可以直接构造,只要交叉着放就好了,比如1 3 5 2 4和2 4 1 3 5,每一行和下一行用不同的方法就能保证没有邻居。

  其他的可以用爆搜,每次暴力和后面的一个编号交换并判断可行性。

  写dfs的话其实行和列>4的就不用刻意构造了,这个dfs方法可以$O(n*m)$跑出一个构造方案。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=;
int n, m;
int pos[maxn];
int dx[]={, , , -}, dy[]={, , -, };
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
bool check(int i, int j)
{
int x=(i-)/m+, y=(i-)%m+, x2=(j-)/m+, y2=(j-)%m+;
for(int k=;k<;k++) if(x+dx[k]==x2 && y+dy[k]==y2) return ;
return ;
}
bool dfs(int i)
{
if(i==n*m+) return ;
int x=(i-)/m+, y=(i-)%m+;
for(int j=i;j<=n*m;j++)
{
swap(pos[i], pos[j]);
if(x!= && check(pos[i], pos[(x-)*m+y])) continue;
if(y!= && check(pos[i], pos[(x-)*m+y-])) continue;
if(dfs(i+)) return ;
swap(pos[i], pos[j]);
}
return ;
}
int main()
{
read(n); read(m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
pos[(i-)*m+j]=(i-)*m+j;
if(!dfs()) return puts("NO"), ;
puts("YES");
for(int i=;i<=n;i++, puts(""))
for(int j=;j<=m;j++)
printf("%d ", pos[(i-)*m+j]);
}