poj3276(开关问题)

来源:互联网 发布:好的电子书软件 编辑:程序博客网 时间:2024/06/06 11:01
  1. 可算明白了..
BBFBFBB

我们到达第三个F,我们需反转。标记一下在3出反转了(vis[3]=1). 对以后的影响是+1.,用sum记载影响程度即sum=1;
我们到达第四个,虽然是B,但是收到前面影响(sum==1),也就是变成F了。我们需要反转。标记vis[4]=1. ,sum再+1.即sum=2;
也就是第五个会受到sum=2个影响。以此类推。 不过到达第i个时,第i个不会受到超出k的反转的影响。所以说if(i-k+1>0) sum-=vis[i-k+1].  这个vis不是0就是1,这样来控制sum。

到了最后一组了,就没办法翻转了,如果剩余的是正的,那就继续往下周。如果不是正的,就不要翻转了,而是直接输出-1.











  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4.   
  5. using namespace std;  
  6. const int maxn = 5000 + 5;  
  7.   
  8. int dir[maxn], n, f[maxn];  //f[i]=1:面向后方       f[i]=0面向前方  
  9.   
  10. int compute(int k)  //计算连续反转k头牛需要几次操作?  
  11. {  
  12.     memset(f, 0, sizeof(f));  
  13.     int res = 0, sum = 0;  
  14.   
  15.     for(int i = 0; i+k-1 <= n-1; i++){  
  16.         if((sum + dir[i]) & 1){  
  17.             res++;  
  18.             f[i] = 1;  
  19.         }  
  20.         sum += f[i];  
  21.         if(i-k+1 >= 0)   sum -= f[i-k+1];  
  22.     }  
  23.   
  24.     for(int i = n-k+1; i < n; i++){  
  25.         if((sum + dir[i]) & 1)  return -1;  
  26.         if(i - k + 1 >= 0)   sum -= f[i-k+1];  
  27.     }  
  28.     return res;  
  29. }  
  30.   
  31. int main()  
  32. {  
  33.     //freopen("in.txt", "r", stdin);  
  34.     while(~scanf("%d", &n)){  
  35.         char tmp[5];  
  36.         memset(dir, 0, sizeof(dir));  
  37.         for(int i = 0; i < n; i++){  
  38.             cin >> tmp;  
  39.             if(tmp[0] == 'B')   dir[i] = 1;  
  40.             else                dir[i] = 0;  
  41.         }  
  42.   
  43.         int ans_k = 1, ans_cnt = n;  
  44.         for(int k = 1; k <= n; k++){  
  45.             int cnt = compute(k);  
  46.             if(cnt < ans_cnt && cnt >= 0){  
  47.                 ans_cnt = cnt;  
  48.                 ans_k = k;  
  49.             }  
  50.         }  
  51.         printf("%d %d\n", ans_k, ans_cnt);  
  52.     }  

  1.     return 0;  

原创粉丝点击