题目1
思路 (递推)
我们可以通过题目条件,找出来本题的一些性质
- 每两个相邻砖块至多操作一次
通过这个性质,我们可以递推的求每个砖块是否被操作,假设砖块变成白色,如果操作第\(i\)个和第\(i + 1\)砖块后,不能使第\(i\)个砖块变为W
, 则不进行该操作,因为后续操作无法使该砖块变为W
。黑色同理
Code
#include <iostream>
#include <vector>
using i64 = long long;
void solve() {
int n;
std::string t;
std::cin >> n >> t;
std::vector<int> act1, act2;
int ans1, ans2;
ans1 = ans2 = 0;
// bool a1 = true, a2 = true;
// for(auto &x: t) {
// if(x != 'W') a1 = false;
// if(x != 'B') a2 = false;
// }
// if(a1 || a2) {
// return puts("0"), (void) 0;
// }
auto flip = [](char &a) {
a = (a == 'W'?'B':'W');
};
std::string t2 = t;
for(int i = 0; i < (int)t2.size() - 1; i ++) {
flip(t2[i]), flip(t2[i + 1]);
if(t2[i] != 'W') {
flip(t2[i]), flip(t2[i + 1]);
} else {
ans1 ++, act1.push_back(i);
}
}
bool st1 = true;
for(auto &x: t2) {
if(x != 'W') st1 = false;
}
if(!st1) ans1 = 0x3f3f3f3f;
t2 = t;
for(int i = 0; i < (int) t2.size() - 1; i ++) {
flip(t2[i]), flip(t2[i + 1]);
if(t2[i] != 'B') {
flip(t2[i]), flip(t2[i + 1]);
} else {
ans2 ++, act2.push_back(i);
}
}
bool st2 = true;
for(auto &x: t2) {
if(x != 'B') st2 = false;
}
if(!st2) ans2 = 0x3f3f3f3f;
if(!st1 && !st2) {
puts("-1");
} else if(ans1 < ans2) {
std::cout << ans1 << "\n";
for(int i = 0; i < ans1; i ++) {
std::cout << act1[i] + 1 << " \n"[i == ans1 - 1];
}
} else {
std::cout << ans2 << "\n";
for(int i = 0; i < ans2; i ++) {
std::cout << act2[i] + 1 << " \n"[i == ans2 - 1];
}
}
}
int main() {
int _;
std::cin >> _;
while(_ --) {
solve();
}
}
题目2
思路 (递推)
性质:每个灯至多被操作一次
这道题做过很多次了,属于是典中典的题了,我们一行一行的递推,我们先枚举第一行的状态,然后对于当前的状态依次往下递推,如果第\(i - 1\)行的灯没有被点亮那么我们的状态是确定的,即第\(i - 1\) 行的灯只能被第\(i\)行点亮,并且如果第\(i\)行的灯没有被点亮,则第\(i - 1\)行不能进行操作, 所以第\(i - 1\)行的灯确定了第\(i\)行的操作。
Code
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using i64 = long long;
/*
性质:
每盏灯最多操作一次
思路: 先枚举第一行的状态, 然后进行递归
第一行的状态确定了,第二行的状态也自然确定了!
*/
char a[10][10], tmp[10][10];
int dx[] = {0, 1, -1, 0}, dy[] = {1, 0, 0, -1};
int ans;
void flip(char &x) {
x = (x == '0'?'1':'0');
}
bool check(int x, int y) {
return x >= 1 && x <= 5 && y >= 1 && y <= 5;
}
void four_flip(int x, int y) {
flip(tmp[x][y]);
for(int j = 0; j <= 3; j ++) {
int tx = x + dx[j], ty = y + dy[j];
if(check(tx, ty)) {
flip(tmp[tx][ty]);
}
}
}
bool check(char a[]) {
for(int i = 1; i <= 5; i ++) {
if(a[i] != '1') return false;
}
return true;
}
void dfs(int u, int cnt) {
for(int j = 1; j <= 5; j ++) {
if(tmp[u - 1][j] != '1') {
four_flip(u, j);
cnt ++;
if(cnt > 6) return;
}
}
if(u == 5) {
if(check(tmp[u])) {
ans = std::min(ans, cnt);
}
return;
}
dfs(u + 1, cnt);
}
void solve() {
ans = INF;
for(int i = 1; i <= 5; i ++) {
for(int j = 1; j <= 5; j ++) {
std::cin >> a[i][j];
}
}
for(int s = 0; s < (1<<5); s ++) {
memcpy(tmp, a, sizeof a);
int cnt = 0;
for(int j = 0; j < 5; j ++) {
if(s >> j & 1) {
cnt ++;
four_flip(1, j + 1);
}
}
// tmp[1][6] = '\0';
// printf("%s\n\n", tmp[1] + 1);
dfs(2, cnt);
}
std::cout << (ans <= 6?ans:-1) << "\n";
}
int main() {
int _;
std::cin >> _;
while(_ --) {
solve();
}
}