Checker —AtCoder - 3876
Problem Statement
AtCoDeer is thinking of painting an infinite two-dimensional grid in a checked pattern of side K. Here, a checked pattern of side K is a pattern where each square is painted black or white so that each connected component of each color is a K × K square. Below is an example of a checked pattern of side 3:
AtCoDeer has N desires. The i-th desire is represented by xi, yi and ci. If ci is B, it means that he wants to paint the square (xi,yi) black; if ci is W, he wants to paint the square (xi,yi) white. At most how many desires can he satisfy at the same time?
Constraints
1 ≤ N ≤ 105
1 ≤ K ≤ 1000
0 ≤ xi ≤ 109
0 ≤ yi ≤ 109
If i ≠ j, then (xi,yi) ≠ (xj,yj).
ci is B or W.
N, K, xi and yi are integers.
Input
Input is given from Standard Input in the following format:
N K
x1 y1 c1
x2 y2 c2
:
xN yN cN
Output
Print the maximum number of desires that can be satisfied at the same time.
Sample Input 1
4 3
0 1 W
1 2 W
5 3 B
5 4 B
Sample Output 1
4
He can satisfy all his desires by painting as shown in the example above.
Sample Input 2
2 1000
0 0 B
0 1 W
Sample Output 2
2
Sample Input 3
6 2
1 2 B
2 1 W
2 2 B
1 0 B
0 6 W
4 5 W
Sample Output 3
4
解析
啦啦啦,面对这道题我们首先要明白题意(就是因为题意理解错误,害我废了多少时间……):此题大概讲述的是,有一张无限大的’棋盘’,然后那张棋盘里包括了无数的k*k的小的方框,求一个原点,使得与规定的点的坐标尽量相同。
这道题,我们可以看出:它并不是一道算法题,那么,我们应该怎么思考呢?大体思路如下:
①我们可以看到,这道题的规模还是蛮大的,所以我们首先要做的是降维和移位,当然还有将字符转化为数字组成;
移位:
不难想到,其实移位就是平移:将每一个点的坐标%(2k),但是这不会影响结果吗?答案是不会的,因为*2k或%2k都仅仅是改变了它的位置,而没有改变它的颜色。
如此,我们便可以进行平移的行动,其次,是降维,这个将会在代码中体现。而将字符转化为数字,则单独标记处理即可。
②我们可以通过移动的方式来实现、找到到底有多少个点使我们所需要的。这可以分为两个部分:一是通过移动移动’x轴’(其实是平行于x轴)或’y轴’(其实是平行于y轴)上的线段来不断的’枚举‘(如上图的黄色部分)。二是通过平移’x轴’向上,一则减,一则加。
【代码实现】
#include<cstdio>
#include<cstring>
const int MAXN = 100000;
const int MAXK = 1000;
int x[MAXN + 5], y[MAXN + 5], c[MAXN + 5];
int y1[10 * MAXK + 5];
int main() {
int N, K, Max = 0, cnt = 0;
scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++) {
char ch;
scanf("%d%d %c",&x[i],&y[i],&ch);
x[i] = x[i] % (2*K);//降维
y[i] = y[i] % (2*K);
if( ch == 'W' ) c[i] = 1;
else c[i] = 0;
}
for(int i=0;i<=K;i++)
{
cnt = 0;
memset(y1,0,sizeof(y1));
for(int j=1;j<=N;j++)
{
int p = ( i<=x[j] && x[j] < i+K );
int q = ( 0 <=y[j] && y[j] < K );
//printf("%d %d",p,q);
if( p ^ q == c[j] )//通过位与来实现
{
cnt++;
y1[y[j]] ++;
}
else
{
y1[y[j]] --;
}
}
for(int j=0;j<=K;j++)
{
if( cnt > Max ) Max = cnt;
if( N - cnt > Max ) Max = N - cnt;
if( j != K )
cnt = cnt - y1[j] - y1[K+j];
}
}
printf("%d\n",Max);
}

探讨无限大棋盘上如何最大化满足特定染色需求的问题。需考虑降维及坐标平移技巧,通过枚举策略寻找最优解。
511

被折叠的 条评论
为什么被折叠?



