zoukankan      html  css  js  c++  java
  • poj 3276(反转)

    传送门:Problem 3276

    参考资料:

      [1]:挑战程序设计竞赛

    先献上AC代码,题解晚上再补

    题意:

      John有N头牛,这些牛有的头朝前("F"),有的朝后("B"),John想让所有的牛头都超前。

      现在,John得到了一个机器,每次可以让连续的 K 头牛转向,问最少需要用多少次(M)机器可以使所有的牛头都超前?

    题解:

      变量解释:

        dir[i] : dir[i]=0 -> 第i头牛面朝前;dir[i]=1 -> 第i头牛面朝后

        f[i] : f[i]=0 -> 在第i头牛出不进行反转操作;f[i]=1 -> 在第i头牛出进行反转操作

      首先,需要明白两点:

        (1):交换区间反转的顺序对结果是没有影响的。

        (2):对同一个区间进行两次以上的反转是多余的。

      因此,问题就转化成了求需要被反转的区间的集合。

      定义 k : 每次需要反转的牛的个数(1 <= k <= N)

         i : 第 i 头牛(1 <= i <= N-k+1,初始 i =  1)

        sum : 受前面反转影响([i-k+1,i-1]),来到第 i 头牛,总共反转的次数

        res : 存储反转次数

      (1):对于第i头来说,如果它是面朝后的,则需要一次反转使其面朝前,而之后的反转区间指定不包含此牛。

      (2):判断第i头牛是否需要反转,如果需要,f[i]=1,res++;i++;

      (3):重复(2)过程,直到 i > N-k+1为止

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn=5e3+50;
     5 
     6 int N;
     7 int dir[maxn];
     8 int f[maxn];
     9 
    10 int Calculate(int k)
    11 {
    12     int res=0;
    13     int sum=0;
    14     for(int i=1;i <= N-k+1;++i)
    15     {
    16         if(i-k > 0)//当前的i只受到区间 [i-k+1,i-1] 反转的影响,所以需要去除i-k对i的反转影响
    17             sum -= f[i-k];
    18         if((dir[i]+sum)%2 != 0)//判断dir[i] 是否为偶数,偶数代表面朝前
    19             f[i]=1,res++;
    20         sum += f[i];
    21     }
    22     for(int i=N-k+2;i <= N;++i)//检查后 k-1头牛是否全都面朝前
    23     {
    24         if(i-k > 0)//解释同上
    25             sum -= f[i-k];
    26         if((dir[i]+sum)%2 != 0)
    27             return -1;
    28     }
    29     return res;
    30 }
    31 void Solve()
    32 {
    33     int K=1,M=N;
    34     for(int k=1;k <= N;++k)//每次反转 k 头牛
    35     {
    36         int m=Calculate(k);
    37         if(m != -1 && m < N)
    38             K=k,M=m;
    39     }
    40     printf("%d %d
    ",K,M);
    41 }
    42 
    43 int main()
    44 {
    45     scanf("%d",&N);
    46     for(int i=1;i <= N;++i)
    47     {
    48         getchar();
    49         char ch=getchar();
    50         dir[i]=(ch == 'F' ? 0:1);
    51     }
    52     Solve();
    53 }
    View Code
  • 相关阅读:
    多表联查统计数字
    在null情况下判断
    一个搜索框实现同一表内多个属性的搜索
    分页固定显示信息数
    git常用命令
    java 常用知识点
    Win10 系统直接在目录下打开cmd
    Linux环境 通过sftp启动jar包
    使用Navicat导出可执行脚本 SqlServer数据库某表的部分数据
    C#常用快捷键
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9802218.html
Copyright © 2011-2022 走看看