题解:P15042 [UOI 2022 II Stage] 双色图形
一道非常适合构造新手入门的简单构造题。
思路
题意较为简单,就不简述了。
我们先不妨假设黑少白多,这时我们可以从极限的情况入手:即再加一个白格就无法构造出合法方式的情况,如下图所示:
先说结论:按此样式构造为最极限的情况,白子多于黑子数目三倍加一即无合法方案。
证明:
我们考虑让每个黑子消耗更多的白子,由题中联通的定义可得:每个黑子最多消耗
但是我们需要保持联通,即一个白子周围不能有其它白子,此时我们会发现这个联通块被“孤立”了,所以我们必须牺牲一个白子来保持联通:
代码:
//比较丑陋,dalao不要抨击我qwq。
#include<bits/stdc++.h>
#define ll long long
#define dd double
#define fs first
#define sc second
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}//快读
int w,b;
string s[4];
int main(){
w=read();
b=read();
int minn=min(w,b);
int maxx=max(w,b);
if(maxx>3*minn+1){
cout<<-1;
return 0;
}//无合法方案
cout<<3<<' ';//棋盘宽度3即可满足
if(w==b){
cout<<b+w<<'\n';
for(int i=1;i<=w+b;i++) cout<<'.';
cout<<'\n';
for(int i=1;i<=w;i++) cout<<"BW";
cout<<'\n';
for(int i=1;i<=w+b;i++) cout<<'.';
return 0;
}//(其实这部分可以和下面合并的)
if(w>b){
cout<<2*b<<'\n';//棋盘长度
for(int i=1;i<=b;i++) s[2]+="WB";
int x=w-b;
if(w==3*b+1) s[2]+="W",x--;
for(int i=1;i<=(x+1)/2;i++) s[1]+=".W";
while(s[1].size()<s[2].size()) s[1]+='.';
for(int i=1;i<=x-(x+1)/2;i++) s[3]+=".W";
while(s[3].size()<s[2].size()) s[3]+='.';
cout<<s[1]<<'\n'<<s[2]<<'\n'<<s[3];
return 0;
}//先填满中间一行,再填第一、三行。
if(b>w){
cout<<2*w<<'\n';
for(int i=1;i<=w;i++) s[2]+="BW";
int x=b-w;
if(b==3*w+1) s[2]+="B",x--;
for(int i=1;i<=(x+1)/2;i++) s[1]+=".B";
while(s[1].size()<s[2].size()) s[1]+='.';
for(int i=1;i<=x-(x+1)/2;i++) s[3]+=".B";
while(s[3].size()<s[2].size()) s[3]+='.';
cout<<s[1]<<'\n'<<s[2]<<'\n'<<s[3];
return 0;
}//跟上面同理
return 0;
}