CF412A Poster 题解
Content
有一个长为 \(n\) 的口号,需要贴在公开场合。一个工人在 \(k\) 处,每次操作,他可以往左移动一格(在输出中用 \(\texttt{LEFT}\) 来表示),也可以往右移动一格(在输出中用 \(\texttt{RIGHT}\) 来表示),也可以粉刷当前没粉刷的字母(在输出中用 \(\texttt{PRINT x}\) 来表示,其中 \(\texttt{x}\) 表示要粉刷的字母),试设计一个操作方案,使得工人的操作数最少,输出这个方案(如果有多种方案输出任意一个即可)。
数据范围:\(1\leqslant k\leqslant n\leqslant 100\)。
Solution
模拟题目,需要有些耐心。
首先我们需要对 \(n\) 的奇偶性来分类讨论:
一、当 \(2\mid n\) 时,再根据 \(k\) 来分类讨论:
- 如果 \(k\leqslant n\div 2\),那么最优方案为不停往左移动直至第一格,再重复粉刷每一格的字符之后往右移动一格的操作直至到了第 \(n\) 格。
- 否则,最优方案为不停往右移动直至第 \(n\) 格,再重复粉刷每一格的字符之后往左移动一格的操作直至到了第一格。
二、当 \(2\nmid n\) 时,再根据 \(k\) 来分类讨论。
- 如果 \(k<\left\lfloor n\div 2\right\rfloor+1\),那么最优方案为不停往左移动直至第一格,再重复粉刷每一格的字符之后往右移动一格的操作直至到了第 \(n\) 格。
- 如果 \(k>\left\lfloor n\div 2\right\rfloor+1\),那么最优方案为不停往右移动直至第 \(n\) 格,再重复粉刷每一格的字符之后往左移动一格的操作直至到了第一格。
- 否则,如果 \(k=\left\lfloor n\div 2\right\rfloor+1\),那么你既可以先不停往左走,也可以先不停往右走,反正最小操作数是一样的。
分类讨论完之后,剩下的就只有根据这些模拟了。
Code
本题解只贴核心代码部分,其中:
- \(n\) 为口号长度。
- \(cur\) 为当前工人所在位置(初始位置为 \(k\))。
- \(a\) 为要张贴的口号。
if(n % 2) {
if(cur <= n / 2 + 1) {
while(cur > 1) {
puts("LEFT");
cur--;
}
while(cur < n) {
printf("PRINT %c\nRIGHT\n", a[cur]);
cur++;
}
printf("PRINT %c", a[cur]);
} else {
while(cur < n) {
puts("RIGHT");
cur++;
}
while(cur >= 2) {
printf("PRINT %c\nLEFT\n", a[cur]);
cur--;
}
printf("PRINT %c", a[cur]);
}
} else {
if(cur <= n / 2) {
while(cur > 1) {
puts("LEFT");
cur--;
}
while(cur < n) {
printf("PRINT %c\nRIGHT\n", a[cur]);
cur++;
}
printf("PRINT %c", a[cur]);
} else {
while(cur < n) {
puts("RIGHT");
cur++;
}
while(cur >= 2) {
printf("PRINT %c\nLEFT\n", a[cur]);
cur--;
}
printf("PRINT %c", a[cur]);
}
}

浙公网安备 33010602011771号