poj3276 Face The Right Way(反转问题,好题)

Posted Surprisez

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3276 Face The Right Way(反转问题,好题)相关的知识,希望对你有一定的参考价值。

https://vjudge.net/problem/POJ-3276

首先意识到,对一个区间进行两次及以上的反转是没有意义的,而且反转次序不影响最终结果。

有点像二分搜索时用的逐个试的方法,每次翻的个数从1~n,然后进入函数判断。

由于正反性可以很巧妙地利用计数的奇偶来判断,所有这里优化复杂度,用f[i]记录i~i+k-1是否翻转了,不断向右判断,如果是反面就反转接下来的一组,直至最后,最后剩的几个如果全正就说明可以,如果有反面就说明不行。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<map>
 8 #define lson l, m, rt<<1
 9 #define rson m+1, r, rt<<1|1
10 #define INF 0x3f3f3f3f
11 typedef unsigned long long ll;
12 using namespace std;
13 int n, a[5010], f[5010];//f是i~i+k-1的是否翻了 
14 char c;
15 int calc(int k)
16 {
17     memset(f, 0, sizeof(f));//每一次都要初始化f 
18     int sum=0, res=0;
19     for(int i = 0; i <= n-k; i++){
20         if(!((a[i]+sum)&1)){//判断该点是反,需要翻转 
21             f[i] = 1;
22             res++;
23         }
24         sum += f[i]; 
25         if(i-k+1>=0)
26             sum -= f[i-k+1];
27     }
28     for(int i = n-k+1; i < n; i++){
29         if(!((a[i]+sum)&1)){
30             return -1;
31         }
32         if(i-k+1>=0)
33             sum -= f[i-k+1];
34     }
35     return res;
36 }
37 int main()
38 {
39     cin >> n;
40     for(int i = 0; i < n; i++){
41         cin >> c;
42         if(c == B) a[i] = 0;
43         else a[i] = 1;
44     }
45     memset(f, 0, sizeof(f));
46     int mini = INF, ans=-1;
47     for(int i = 1; i <= n; i++){
48         int num = calc(i);
49         //cout << i << " " << num << endl;
50         if(num>0&&num<mini){
51             mini = num;
52             ans = i;
53         }
54     }
55     cout << ans << " " << mini << endl;
56     return 0;
57 }

 

以上是关于poj3276 Face The Right Way(反转问题,好题)的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 3276 Face The Right Way

Face The Right Way(POJ 3276)

POJ3276 Face The Right Way (尺取法)

POJ 3276 Face The Right Way 开关问题

poj3276 Face The Right Way

poj3276 Face The Right Way