📅  最后修改于: 2023-12-03 14:58:37.273000             🧑  作者: Mango
题目描述:给定四个门和一个机关,机关只能当门都关上时才能打开,每次可以选择其中两个门,如果它们都开着就把它们都关上,否则就把它们都打开。
我们需要写一个程序来模拟这个过程,即输入起始状态(门的开闭状态),输出最终状态(机关是否打开)。
这是一道典型的状态搜索问题,我们可以用一个长度为16的二进制数来表示当前状态,其中每一位代表一个门的开闭状态,0表示门关闭,1表示门开启。
先定义一个函数operator(state,a,b)
,输入当前状态state
和选中的两个门的编号a
和b
,返回更新后的状态。
具体实现是:首先判断a
和b
门的状态,如果两个门都是开着的,就把它们全部关闭;如果两个门都是关着的,就把它们全部打开;否则的话就不用管它们了。
定义一个队列q
,并将起始状态加入队列。
用一个unordered_set
(C++11中的一种哈希表,可以在常数时间内判断一个元素是否在集合中)来保存已经搜索过的状态。每次从队列中取出一个状态,判断它是否是目标状态(即所有门都关闭),如果是,就直接返回;否则枚举两个门的组合,得到新状态,如果新状态没有搜索过就加入队列,并把它标记为已搜索过。
最终如果整个队列都被搜索完了还没有找到目标状态,就说明无解。
struct State {
unsigned short value;
bool operator<(const State& rhs) const {
return value < rhs.value;
}
};
State operator&(const State& lhs, const State& rhs) {
return {lhs.value & rhs.value};
}
State operator~(const State& state) {
return {~state.value};
}
bool operator==(const State& lhs, const State& rhs) {
return lhs.value == rhs.value;
}
bool operator!=(const State& lhs, const State& rhs) {
return lhs.value != rhs.value;
}
State operator^(const State& lhs, const State& rhs) {
return {lhs.value ^ rhs.value};
}
State operator|(const State& lhs, const State& rhs) {
return {lhs.value | rhs.value};
}
State operator|(const State& lhs, unsigned short rhs) {
return {lhs.value | rhs};
}
State operator<<(const State& lhs, int rhs) {
return {lhs.value << rhs};
}
State operator>>(const State& lhs, int rhs) {
return {lhs.value >> rhs};
}
State operator+(const State& lhs, const State& rhs) {
return lhs ^ rhs;
}
bool IsDoorOpen(const State& state, int idx) {
return state.value & (1 << idx);
}
State CloseDoor(State state, int idx) {
state.value &= ~(1 << idx);
return state;
}
State OpenDoor(State state, int idx) {
state.value |= (1 << idx);
return state;
}
State operator|(const State& lhs, const std::vector<int>& rhs) {
State result = lhs;
for (int idx : rhs) {
result = OpenDoor(result, idx);
}
return result;
}
int bfs(State start) {
std::unordered_set<State> visited;
std::queue<State> q;
q.push(start);
visited.insert(start);
while (!q.empty()) {
State cur_state = q.front();
q.pop();
bool all_closed = true;
for (int i = 0; i < 4; ++i) {
if (IsDoorOpen(cur_state, i)) {
all_closed = false;
break;
}
}
if (all_closed) {
return 0;
}
for (int i = 0; i < 4; ++i) {
for (int j = i + 1; j < 4; ++j) {
State new_state = operator|(cur_state, std::vector{i, j});
if (visited.count(new_state) == 0) {
q.push(new_state);
visited.insert(new_state);
}
}
}
}
return -1;
}
int main() {
int start_state = 0;
for (int i = 0; i < 4; ++i) {
char c;
std::cin >> c;
if (c == '1') {
start_state |= (1 << i);
}
}
int res = bfs(State{start_state});
if (res == -1) {
std::cout << "impossible" << std::endl;
} else {
std::cout << res << std::endl;
}
return 0;
}
markdown标记:代码用三个撇括起来,并指定语言(本程序是C++);公式用一个撇括起来。
// 代码放在这里
$E=mc^2$