码迷,mamicode.com
首页 > 其他好文 > 详细

挑战程序竞赛 反转开关 poj3276

时间:2019-08-03 21:45:40      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:print   article   inf   isp   sed   one   turn   char   img   

这个我其实也没有看太懂它的证明过程。

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

标签:print   article   inf   isp   sed   one   turn   char   img   

原文地址:https://www.cnblogs.com/EchoZQN/p/11296222.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!