挑战程序竞赛 反转开关 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

 

以上是关于挑战程序竞赛 反转开关 poj3276的主要内容,如果未能解决你的问题,请参考以下文章

poj3185 开关问题

反转(开关问题)poj 3276 POJ3279

POJ - 3276 开关问题

挑战程序设计竞赛2.2习题:Allowance POJ - 3040

挑战程序设计竞赛2.3:Wooden Sticks POJ - 1065

挑战程序设计竞赛2.3习题:Cheapest Palindrome POJ - 3280