题目大意:给定一个20的数组,全都是0和1,可以翻一个数改变成另一个数(0或者1),但是其左右两边的数都会跟着变为原来的相反数,问你怎么用最小的操作数使全部数变成0
这一题的:满足
1:翻转次序不改变结果
2. 从特定次序翻转以后左侧的元素不会再改变
其实就是3276的变形,只是他这次固定变三个数,而且是一前一后,我们把方向dir的查看往前挪一个数就好了,但是这样我们就不能知道第一个数是否需要翻转,所以我们分两种情况来讨论就好了
一开始我想着像3279那样枚举,可是1<<20次实在是太大了,结果TLE
#include <iostream> #include <algorithm> #include <functional> using namespace std; static int bowls[21], if_flip[21]; int solve(void); int get_step(int); int main(void)//开关问题 { for (int i = 1; i <= 20; i++) scanf("%d", &bowls[i]); printf("%d ", solve()); return EXIT_SUCCESS; } int solve()//所有输入都能有一个固定的值 { //if_flip[i]:=i~i+1需要翻转就是1,否则就是0 int sum = 0, res = INT_MAX; memset(if_flip, 0, sizeof(if_flip)); res = min(res, get_step(0)); memset(if_flip, 0, sizeof(if_flip)); res = min(res, get_step(1)); return res; } int get_step(int sum)//关键问题就是第一个要不要翻,如果要翻那就是0,否则就是1 { int i, res = sum; if_flip[1] = sum; for (i = 2; i <= 20; i++) { if ((sum + bowls[i - 1]) % 2 == 1) { res++; if_flip[i] = 1; } sum += if_flip[i]; sum -= if_flip[i - 2]; } if ((bowls[20] + sum) % 2 == 1) return INT_MAX; else return res; }