博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Face The Right Way(POJ 3276)
阅读量:4343 次
发布时间:2019-06-07

本文共 3258 字,大约阅读时间需要 10 分钟。

  • 原题如下:
    Face The Right Way
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 6708   Accepted: 3124

    Description

    Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing forward, like good cows. Some of them are facing backward, though, and he needs them all to face forward to make his life perfect.

    Fortunately, FJ recently bought an automatic cow turning machine. Since he purchased the discount model, it must be irrevocably preset to turn K (1 ≤ K ≤ N) cows at once, and it can only turn cows that are all standing next to each other in line. Each time the machine is used, it reverses the facing direction of a contiguous group of K cows in the line (one cannot use it on fewer than K cows, e.g., at the either end of the line of cows). Each cow remains in the same *location* as before, but ends up facing the *opposite direction*. A cow that starts out facing forward will be turned backward by the machine and vice-versa.

    Because FJ must pick a single, never-changing value of K, please help him determine the minimum value of K that minimizes the number of operations required by the machine to make all the cows face forward. Also determine M, the minimum number of machine operations required to get all the cows facing forward using that value of 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

    7BBFBFBB

    Sample Output

    3 3

    Hint

    For 
    K = 3, the machine must be operated three times: turn cows (1,2,3), (3,4,5), and finally (5,6,7)
  • 题解:对于一个特定的K如何求出让所有的牛面朝前方的最小操作次数?首先,交换区间反转的顺序对结果是没有影响的,另外,可以知道对同一个区间进行两次以上的反转是多余的,由此,问题就转化成了求需要反转的区间的集合。先考虑一下最左端的牛,因为包含这头牛的区间只有一个,所以如果这头牛面朝前方,我们就能知道这个区间不需要反转,反之如果这头牛面朝后方,对应的区间就必须进行反转了,而且在此之后的最左区间就再也不需要考虑了,这样一来通过首先考虑最左端的牛,问题的规模就缩小了1,不断地重复下去,就可以无需搜索求出最少所需反转次数了。通过前面的分析可以知道,忽略掉对同一个区间重复反转这类多余操作之后,只要存在让所有的牛都朝前的方法,那么操作就和顺序无关,可以唯一确定了。对于整个算法的话,我们需要对所有的K都求解一次,对于每个K最坏情况下需要进行N-K+1次的反转操作,每次操作又要反转K头牛,于是总的复杂度是O(N3)。区间反转的部分还可以进行优化,令f[i]:=区间[i,i+K-1]进行了反转的话为1,否则为0,这样在考虑第i头牛时,如果∑(j=i-K+1,i-1)f[j]为奇数的话,则这头牛的方向与起始方向是相反的,否则方向不变,由于∑(j=(i+1)-K+1,i)f[j] = ∑(j=i-K+1,i-1)f[j]+f[i]-f[i-K+1],所以这个和每一次都可以用常数时间计算出来,复杂度就降为了O(N2),就可以在时限内解决问题了。
  • 代码:
    1 #include 
    2 #include
    3 #include
    4 #include
    5 #include
    6 #define num s-'0' 7 8 using namespace std; 9 10 const int MAX_N=5001;11 const int INF=0x3f3f3f3f;12 int N;13 int dir[MAX_N], f[MAX_N];14 15 void read(int &x){16 char s;17 x=0;18 bool flag=0;19 while(!isdigit(s=getchar()))20 (s=='-')&&(flag=true);21 for(x=num;isdigit(s=getchar());x=x*10+num);22 (flag)&&(x=-x);23 }24 25 void write(int x)26 {27 if(x<0)28 {29 putchar('-');30 x=-x;31 }32 if(x>9)33 write(x/10);34 putchar(x%10+'0');35 }36 37 int calc(int);38 39 int main()40 {41 read(N);42 for (int i=0; i
    =1; k--)51 {52 int m=calc(k);53 if (m>=0 && m
    =0) sum-=f[i-K+1];76 }77 for (int i=N-K+1; i
    =0) sum-=f[i-K+1];81 }82 return res;83 }

     

转载于:https://www.cnblogs.com/Ymir-TaoMee/p/9509493.html

你可能感兴趣的文章
安卓开发环境搭建
查看>>
.NET日志工具 log4net
查看>>
线段树整理
查看>>
Windows、mac字体安装教程
查看>>
A Dog's Way Home插曲列表
查看>>
计算机体系结构——流水线技术(Pipelining)
查看>>
k8s 常用命令
查看>>
几种任务调度的 Java 实现方法与比较
查看>>
EF5.0默认不支持DB First了?
查看>>
sap alv 单元格行列邓颜色设定(记录一下网址,供下次使用)
查看>>
四大算法解决最短路径问题(Dijkstra+Bellman-ford+SPFA+Floyd)
查看>>
时间日期——————年月日的的处理
查看>>
UVA 127 - "Accordian" Patience
查看>>
多态抽象类学习
查看>>
pom
查看>>
linux学习2-压缩与解压
查看>>
在 Sublime Text 直接运行 Javascript 调试控制台
查看>>
字符串修改问题
查看>>
九宫图Css
查看>>
ie9实现flex布局3等分
查看>>