首页 > 其他 > 详细

挑战程序竞赛 反转开关 poj3276

时间:2019-08-03 21:59:11      阅读:85      评论:0      收藏:0      [点我收藏+]

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

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

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!