Codeforces Round #575 (Div. 3)
E - Connected Component on a Chessboard
You are given two integers b and w. You have a chessboard of size 109×109 with the top left cell at (1;1), the cell (1;1) is painted white.
Your task is to find a connected component on this chessboard that contains exactly b black cells and exactly w white cells. Two cells are called connected if they share a side (i.e. for the cell (x,y) there are at most four connected cells: (x−1,y),(x+1,y),(x,y−1),(x,y+1)). A set of cells is called a connected component if for every pair of cells C1 and C2 from this set, there exists a sequence of cells c1, c2, ..., ck such that c1=C1, ck=C2, all ci from 1 to k are belong to this set of cells and for every i∈[1,k−1], cells ci and ci+1 are connected.
Obviously, it can be impossible to find such component. In this case print "NO". Otherwise, print "YES" and any suitable connected component.
You have to answer q independent queries.
Input
The first line of the input contains one integer q (1≤q≤105) — the number of queries. Then q queries follow.
The only line of the query contains two integers b and w (1≤b,w≤105) — the number of black cells required and the number of white cells required.
It is guaranteed that the sum of numbers of cells does not exceed 2⋅105 (∑w+∑b≤2⋅105).
Output
For each query, print the answer to it.
If it is impossible to find the required component, print "NO" on the first line.
Otherwise, print "YES" on the first line. In the next b+w lines print coordinates of cells of your component in any order. There should be exactly b black cells and w white cells in your answer. The printed component should be connected.
If there are several answers, you can print any. All coordinates in the answer should be in the range [1;109].
Example
input
3
1 1
1 4
2 5
output
YES
2 2
1 2
YES
2 3
1 3
3 3
2 2
2 4
YES
2 3
2 4
2 5
1 3
1 5
3 3
3 5
题意:题目意思是给你个黑白格子相邻的10^9 * 10^9 棋盘给你,(1,1)位置为白,然后相邻格子连接称为联通,
给你一个黑色单元格数和白色单元格数,让你找出由这些格数组成的联通块,
能找出输出 "YES" ,和每个格子坐标,找不到输出 "NO" 。
思路:我们首先可以发现 坐标 (x,y)的点,(x+y)%2=1时为黑格,(x+y)%2=0时为白格。
另外:联通块中 设黑格子数为 hei,白格子数为 bai ,有结论
当 黑格数少时,hei <= bai*3+1 ;当白格数少时 bai <= hei*3+1 。因为最大构成情况就是 几个十字型的形状连续组合在一起,
其中十字中间格颜色跟相邻上下左右颜色肯定是不同的,(可以自己在纸上画一画思考下)。那么我们就可以根据这种形状来构造联通块,
就是一直构造十字型的左半边(上中下左),当后面格子数剩余时可以用bfs解决。
由于黑白格子数数量多少基本是同一个问题,只是中心构造起点不同,那我们可以用个交换函数归为一种情况,(写的有点复杂)。
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<map>
6 #include<set>
7 #include<vector>
8 #include<algorithm>
9 #include<queue>
10 #include<unordered_map>
11 using namespace std;
12 #define ll long long
13 const int mod=1e9+7;
14 const int inf=1e9+7;
15
16 const int maxn=1e9-1;
17
18 int nextt[4][2]={{-1,0},{0,1},{0,-1},{1,0}};//左上下,右
19
20 int main()
21 {
22 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
23 int T;
24 cin>>T;
25 int hei,bai;
26 while(T--)
27 {
28 cin>>hei>>bai;//输入黑格子数,白格子数
29 int x,y,tx,ty,nowx,nowy;
30 vector<pair<int,int>>v_hei;//装黑格坐标
31 vector<pair<int,int>>v_bai;//装白格坐标
32 map<pair<int,int>,int>book;//标记走过的坐标
33 if(hei>=bai)// 黑格子数多
34 {
35 x=2;
36 y=2;
37 }
38 else
39 {
40 swap(hei,bai);//交换
41 x=2; //和上面情况相同
42 y=3;
43 }
44 if(hei>bai*3+1)//不符合
45 {
46 cout<<"NO"<<endl;
47 continue;
48 }
49 //第一个白格坐标
50 //黑格子数多,以白格子数为中心,周围放黑格子
51 book[{x,y}]=1;
52 v_bai.push_back({x,y});
53 bai--;//剩下需要的白格数减一
54 while(bai>0)//当白格数大于0
55 {
56 for(int i=0;i<3;i++)
57 {
58 tx=x+nextt[i][0];
59 ty=y+nextt[i][1];
60 if(tx<1||tx>maxn||ty<1||ty>maxn)
61 continue;
62 if(book[{tx,ty}]==0)
63 {
64 book[{tx,ty}]=1;
65 v_hei.push_back({tx,ty});
66 hei--;
67 if(hei==0)
68 break;
69 }
70 }
71 if(hei==0)//不需要黑格子了,退出
72 break;
73 if(bai>0)
74 {
75 x+=2;//白格子现在坐标向右移动
76 //y+=0;
77 v_bai.push_back({x,y});
78 book[{x,y}]=1;
79 bai--;
80 }
81 }
82 while(hei>0)//退出后还需要黑格子,在上次的白格子周围找
83 {
84 for(int i=0;i<v_bai.size();i++)
85 {
86 x=v_bai[i].first;
87 y=v_bai[i].second;
88 for(int j=0;j<4;j++)
89 {
90 tx=x+nextt[j][0];
91 ty=y+nextt[j][1];
92 if(tx<1||tx>maxn||ty<1||ty>maxn)
93 continue;
94 if(book[{tx,ty}]==0)
95 {
96 book[{tx,ty}]=1;
97 v_hei.push_back({tx,ty});
98 hei--;
99 if(hei==0)
100 break;
101 }
102 }
103 if(hei==0)
104 break;
105 }
106 }
107 while(bai>0)//退出后还需要白格子,在上次的黑格子周围找
108 {
109 for(int i=0;i<v_hei.size();i++)
110 {
111 x=v_hei[i].first;
112 y=v_hei[i].second;
113 for(int j=0;j<4;j++)
114 {
115 tx=x+nextt[j][0];
116 ty=y+nextt[j][1];
117 if(tx<1||tx>maxn||ty<1||ty>maxn)
118 continue;
119 if(book[{tx,ty}]==0)
120 {
121 book[{tx,ty}]=1;
122 v_bai.push_back({tx,ty});
123 bai--;
124 if(bai==0)
125 break;
126 }
127 }
128 if(bai==0)
129 break;
130 }
131 }
132 cout<<"YES"<<endl;
133 for(int i=0;i<v_bai.size();i++)
134 cout<<v_bai[i].first<<" "<<v_bai[i].second<<endl;
135 for(int i=0;i<v_hei.size();i++)
136 cout<<v_hei[i].first<<" "<<v_hei[i].second<<endl;
137 }
138
139 return 0;
140 }