当前位置: 代码迷 >> 综合 >> Codeforces Round #454 D. Seating of Students
  详细解决方案

Codeforces Round #454 D. Seating of Students

热度:107   发布时间:2023-10-29 09:37:29.0

题意

就是给你n?m的矩阵
一开始矩阵每个点的坐标就是(i?1)?m+j
然后你需要构造一个新的矩阵
使得新的矩阵没有任何两个坐标在原矩阵中相邻

前言

昨晚看完A就去做D了。。
感觉很浓的构造气息。。
如果n和m大的话,还是很好做的。。
但是小的就不是很好做了。。
在加上很困,于是就没做出来

题解

感觉大体上有两个做法

1.n和m<script type="math/tex" id="MathJax-Element-64">≤</script>5的手玩,大的构造
构造方法还是比较简单的就是奇数大概就是1,3,5,7,9…..2,4,6,8,10…
偶数就反过来

2.随机化
考虑到大的话成功的可能性很大
但是小的话情况不多
于是我们可以考虑随机化。。
大概就是随机填数,然后多次尝试,就可以过了
CODE:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int N=100005;
int n,m;
vector<int> lalal[N];
vector<int> a[N],b[N];
int fx[4]={-1,0,0,1};
int fy[4]={
   0,-1,1,0};
bool ok[N];
bool check (int o,int x,int y)
{if (x<=0||y<=0) return false;int size=lalal[o].size();for (int u=0;u<size;u++)if (lalal[o][u]==b[x][y])return true;return false;
}
int myrand ()
{return rand()*rand()%(n*m)+1;
}
void solve ()
{int num;for (int u=1;u<=n;u++)for (int i=1;i<=m;i++){num=0;int x=myrand();while ((num<=(n*m)*2)&&(ok[x]==false||check(x,u-1,i)||check(x,u,i-1))){x=myrand();num++;}if (num>(n*m)*2)    return ;ok[x]=false;b[u][i]=x;}printf("YES\n");for (int u=1;u<=n;u++){for (int i=1;i<=m;i++)printf("%d ",b[u][i]);printf("\n");}exit(0);
}
int main()
{srand(87);scanf("%d%d",&n,&m);for (int u=1;u<=n;u++){a[u].resize(m+5);b[u].resize(m+5);for (int i=1;i<=m;i++)a[u][i]=(u-1)*m+i;}for (int u=1;u<=n;u++)for (int i=1;i<=m;i++)for (int j=0;j<4;j++){int nx=u+fx[j],ny=i+fy[j];if (nx>=1&&nx<=n&&ny>=1&&ny<=m)lalal[a[u][i]].push_back(a[nx][ny]);}for (int u=1;u<=100;u++){memset(ok,true,sizeof(ok));solve();}printf("NO\n");return 0;
}
  相关解决方案