题解:CF1567F One-Four Overload
yingkeqian9217 · · 题解
提供一种比较好写的直接构造的方法。
::::warning[提示] 以下为笔者的思考过程,可以跳过直接看最后的构造部分。 ::::
容易想到先确定非标记点,限制每个标记点周围和为
发现多边形内外可以分开考虑,且内部问题形式类似。请注意这里的内外是广义的,因为多边形有自交,可以通过光线投射算法判断其内外,即某一方向到边界前经过边数的奇偶性,注意边界情况。
由于对于多边形内部只有角块,所以只要考虑拐角格不同的限制,显然只要按行奇偶性赋值即可。特别的,多边形为空仍成立。
对于多边形内外间,只有边块的限制,只要给内部全部取反即可。
总结一下,对于每个位置的赋值,只要求出其行编号奇偶性和是否在多边形内部的异或和,对应赋
#include<bits/stdc++.h>
using namespace std;
int n,m,a[505][505],ans[505][505];
char c[505][505];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=0;i<n;i++) cin>>c[i];
for(int i=1;i<n-1;i++){
int cur=0,lst=0;
for(int j=m-1;j>=0;j--){
if(j&&j<m-1&&c[i][j]=='X'&&((c[i-1][j]=='.')+(c[i+1][j]=='.')+(c[i][j-1]=='.')+(c[i][j+1]=='.'))&1) return cout<<"NO\n",0;
if(c[i][j]=='X'&&c[i-1][j]=='X'&&c[i+1][j]=='X'){
cur^=1;
continue;
}
if(c[i][j]=='X'&&c[i-1][j]=='X'){
if(lst) cur^=(lst==1),lst=0;
else lst=-1;
continue;
}
if(c[i][j]=='X'&&c[i+1][j]=='X'){
if(lst) cur^=(lst==-1),lst=0;
else lst=1;
continue;
}
if(c[i][j]!='X') ans[i][j]=cur;
}
}
cout<<"YES\n";
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(c[i][j]!='X') cout<<((ans[i][j]^(i&1)?1:4))<<' ';
else cout<<((c[i-1][j]=='.')+(c[i+1][j]=='.')+(c[i][j-1]=='.')+(c[i][j+1]=='.')>>1)*5<<' ';
}
cout<<'\n';
}
return 0;
}