挑战程序竞赛 反转开关 poj3276
Posted echozqn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了挑战程序竞赛 反转开关 poj3276相关的知识,希望对你有一定的参考价值。
这个我其实也没有看太懂它的证明过程。
1.若某一个位置被翻转了n次,则其实际上被翻转了n%2次。
2.分析易知翻转的顺序并不影响最终结果。
3.现在我们着眼于第1个位置,可知若要将第1个位置进行翻转只有翻转它自己,因为没有其他位置的翻转会引起它的翻转。
由①可知若第1个位置为1则必须且进行翻转(并将其后2个进行连带翻转)且以后不再进行翻转,因为再进行翻转就一共翻转了2次相当于没翻转。
然后着眼于第2个位置,由于第1个位置不再进行翻转,所以要想翻转第2个位置只有翻转它自己,因为没有其他位置的翻转会引起它的翻转.....................以此类推直至最后剩下的个数<3个,
因为每次都翻转3个,而剩下的少于3个了就不再进行考虑了,此时只需判断剩下的是否全为0的即可,若不全为0,则不存在全部翻转为0的方案。
以上内容转自 反转(开关问题) Poj3276、3279、3185、1244
不过差不多就这样吧,书上还有一个公式,这个直接看还是很难看懂的,结合一下代码就很简单了。
#include <cstring> #include <queue> #include <cstdlib> #include <cstdio> #include <algorithm> #include <map> #include <vector> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1e5 + 10; int dir[maxn], f[maxn], n; char s[10]; int cul(int x) int sum = 0, res = 0; memset(f, 0, sizeof(f)); for (int i = 1; i + x <= n + 1; i++) if ((dir[i] + sum) % 2 == 0) f[i] = 1; sum++; res++; if (i - x + 1 >= 0) sum -= f[i - x + 1]; sum = 0;; for(int i=1;i<=n;i++) sum += f[i]; if ((dir[i] + sum) % 2 != 1) return -1; if (i - x + 1 >= 0) sum -= f[i - x + 1]; return res; int main() scanf("%d", &n); for(int i=1;i<=n;i++) scanf("%s", s); if (s[0] == ‘F‘) dir[i] = 1; else dir[i] = 0; int ans = inf, mark = 0; for(int i=1;i<=n;i++) int k = cul(i); if(k>=0&&ans>k) ans = k; mark = i; printf("%d %d\n", mark, ans); return 0;
以上是关于挑战程序竞赛 反转开关 poj3276的主要内容,如果未能解决你的问题,请参考以下文章
挑战程序设计竞赛2.2习题:Allowance POJ - 3040