zoukankan      html  css  js  c++  java
  • Face The Right Way [POJ3276] [开关问题]

    题意:

    有n头奶牛排成一排,有的朝前(F)有的朝后(B),现在你可以使k头奶牛一次性翻转朝向(n>=k>=1),问你最少的翻转次数和此时对应的k值。 

    Input

    Line 1: A single integer: N 
    Lines 2.. N+1: Line i+1 contains a single character, F or B, indicating whether cow i is facing forward or backward.

    Output

    Line 1: Two space-separated integers: K and M

    Sample Input

    7
    B
    B
    F
    B
    F
    B
    B

    Sample Output

    3 3

    Analysis

    我们先来观察,可以发现,处理好i前面的点后,如果i这个点是B的话,就必须反向,而反向一次以上的话,是无效的(奇数次与1次等效,偶数次于0次等效)。

    所以我们可以枚举K,然后从1处理到N,如果需要处理,就再套一个循环修改。这样的复杂度是O(N3),仍然不够。

    我们想,如果这个数加上[i-k+1,i-1]的翻转次数,是奇数的话就代表需要切换,然后记录下区间次数和sum每次加上新处理的点,去掉即将在区间外的点。这样,就降到N2

    Code

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register int
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define maxn 5005
    16 using namespace std;
    17 int n,ans1=inf,ans2;
    18 int num[maxn],f[maxn];
    19 char s[5];
    20 inline int read()
    21 {
    22     int x=0,f=1;char c=getchar();
    23     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    24     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    25     return x*f;
    26 }
    27 
    28 int main()
    29 {
    30     n=read();
    31     rep(i,1,n)    {scanf("%s",s);if(s[0]=='B')    num[i]=1;}
    32     rep(k,1,n)
    33     {    
    34         int sum=0,cnt=0;memset(f,0,sizeof(f));
    35         for(RG i=1,lim=n-k+1;i<=lim;++i)
    36         {
    37             if((num[i]+sum)&1)    f[i]=1,cnt++;
    38             sum+=f[i];if(i-k>=0)sum-=f[i-k+1];
    39         }
    40         rep(i,n-k+2,n)
    41         {
    42             if((num[i]+sum)&1)    
    43             {
    44                 cnt=-1;break;
    45             }
    46             sum+=f[i];if(i-k>=0)sum-=f[i-k+1];
    47         }
    48         if(cnt==-1)        continue;
    49         if(cnt<ans1)    ans1=cnt,ans2=k;
    50     }
    51     cout<<ans2<<" "<<ans1;
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    Integer中计算int位数的方法
    Spark学习---常见的RDD转和行动操作
    Spark学习---RDD编程
    《教父》中的经典台词以及英文原版
    关于MATSIM中,如何关闭自动加载dtd的问题
    源发行版8需要目标发行版1.8
    关于Mysql中GROUP_CONCAT函数返回值长度的坑
    【转】通过xml处理sql语句时对小于号与大于号的处理转换
    XmlDocument根据节点的属性值获取节点
    【转】使用SevenZipSharp压缩、解压文件
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9290422.html
Copyright © 2011-2022 走看看