8469.特殊密码锁
- 8469.特殊密码锁
每个按钮有凹和凸两种状态,则n个按钮的状态总数为$ 2^{n} $,显然使用暴力解法会超出时间限制。显而易见,同一个按钮按两次不会有任何效果,因此每个按钮最多的操作次数只能为1。不妨用数组status[n+2]表示按钮的状态,result[n+2]表示期望的目标状态,元素的取值限定为0和1,那么status[i]的翻转会导致status[i-1]和status[i+1]都发生翻转。我们注意到,一旦status[i]发生了改变,由于会波及到status[i+1],所以status[i+1]是否发生改变也被固定死了。由此,我们得到下列解题思路:设置第一个按钮的状态不发生翻转,对比status和result的值,求得操作次数;然后设置第一个按钮的状态发生翻转,再求得操作次数。取次数少者作为输出结果,如果两种操作都不成功,则输出impossible。
在做题时发现一个巨坑,翻转状态时使用非运算~一直不成功,本地DeBug发现~0的结果居然等于-1,后面翻转状态修改为当前位和1进行异或运算,终于成功AC!
#include <bits/stdc++.h> using namespace std; // 重新设计 int main(void) { char line[30]; // input buffer cin >> line; const int N = strlen(line); // length of input string int oriLock[N]; for (int i = 0; i < N; ++i) { oriLock[i] = line[i] - '0'; } cin >> line; int destLock[N]; // get dest lock for (int i = 0; i < N; ++i) { destLock[i] = line[i] - '0'; } // process corner case if (1 == N) { cout << ((oriLock[0] == destLock[0]) ? 0 : 1); return 0; } int result = INT_MAX; // process normal case for (int i = 0; i < 2; ++i) { int lock[N]; for (int j = 0; j < N; ++j) { lock[j] = oriLock[j]; } int count = 0; // flip power0 if (1 == i) { count = 1; // flip 1 time lock[0] ^= 1; lock[1] ^= 1; } for (int idx = 1; idx <= N - 1; ++idx) { // according to destLock to decide lock if (lock[idx -1] != destLock[idx - 1]) { ++count; lock[idx - 1] ^= 1; lock[idx] ^= 1; if (N - 1 != idx) { lock[idx + 1] ^= 1; } } if (N - 1 == idx && lock[idx] == destLock[idx]) { result = min(result, count); } } } if (result != INT_MAX) { cout << result; } else { cout << "impossible"; } return 0; }
浙公网安备 33010602011771号