Face The Right Way POJ - 3276 (开关问题)

Face The Right Way

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 6707   Accepted: 3123

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

7
B
B
F
B
F
B
B

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)

题意:N头牛排成了一排,每头牛都超前或者朝后。为了让所有的牛都头朝前需要一个机器,这个机器可以使得连续的K头牛反转(超前变朝后,朝后变朝前),需要反转M次,求最少的操作次数M和对应的最小值K

思路:显然,一头牛如果反转两次就等于没有反转,所以一头牛要是被反转两次就多余了。一排牛,我们从左往右看的话,如果第一头牛是头朝后的,那么势必这头牛需要被反转,如果这头牛是头朝前的,那么我们就可以从第二头牛开始进行反转如果第二头牛它是头朝后的话,比如如果一排牛是BBFBFBB(F向前,B向后),那么我们从左往右看第一头牛它是朝后的,所以需要反转,我们假设此时的K是3,那么反转后是FFBBFBB,由于我们是为了第一头牛朝前,那么反转一次后第一头牛肯定朝前了,接下去我们发现第二头牛头刚好也是朝前,那么我们就继续往下看第三头,第三头头往后,那么就反转345号牛,结果为FFFFBBB,此时,我们去找第四头牛时发现他也是朝前的,那就继续往下,第五头牛朝后,那么就把567给反转。但最后一次反转后要记得验证是否最后一次使得接下去的K个牛都是头朝前的。而K的找寻这里用了暴力,1-N循环了一遍。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
typedef long long ll;
const int maxn = 5e3+3;
const int mod = 1e9 + 7;
int gcd(int a, int b) {
    if (b == 0) return a;  return gcd(b, a % b);
}

int N,M;
int dir[maxn],f[maxn];      //牛的方向 F:0    B:1

int calc(int K)
{
    memset(f,0,sizeof(f));
    int res=0,sum=0;
    for(int i=0;i+K<=N;i++)
    {
        if((dir[i]+sum)%2!=0)
        {
            res++;
            f[i]=1;
        }
        sum+=f[i];
        if(i-K+1>=0)
            sum-=f[i-K+1];
    }
    for(int i=N-K+1;i<N;i++)    //检查剩下的牛是否有面朝后方的情况
    {
        if((dir[i]+sum)%2!=0)
            return -1;
        if(i-K+1>=0)
            sum-=f[i-K+1];
    }
    return res;
}

void solve()
{
    int K=1;
    int M=N;
    for(int k=1;k<=N;k++)
    {
        int m=calc(k);
        if(m>=0 && M>m)
        {
            M=m;
            K=k;
        }
    }
    cout<<K<<" "<<M<<endl;
}
int main()
{
    scanf("%d",&N);
    int num=0;
    for(int i=0;i<N;i++){
        char ch;
        cin>>ch;
        if(ch==‘B‘)
            dir[num]=1;
        else
            dir[num]=0;
       // cout<<dir[num]<<" ";
        num++;
    }
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/smallhester/p/9501247.html

时间: 2024-08-06 07:12:19

Face The Right Way POJ - 3276 (开关问题)的相关文章

POJ 3276 (开关问题)

题目链接: http://poj.org/problem?id=3276 题目大意:有一些牛,头要么朝前要么朝后,现在要求确定一个连续反转牛头的区间K,使得所有牛都朝前,且反转次数m尽可能小. 解题思路: 首先不要看错题意了,不是求最小K,不要二分.而且反转区间长度一定是K,小于K是不能反转的. 很明显得枚举K(1...n),并且有以下反转思路: ①从第一头牛开始,如果朝前,不管了.看下一头牛,如果朝后反转K长度区间.....一直扫到区间结束. ②第一趟结束后,如果不符合要求,继续重复①,直到所

Face The Right Way poj 3276 开关问题

Language: Default Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 2811   Accepted: 1298 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

反转(开关问题) POJ 3276

POJ 3276 题意:n头牛站成线,有朝前有朝后的的,然后每次可以选择大小为k的区间里的牛全部转向,会有一个最小操作m次使得它们全部面朝前方.问:求最小操作m,再此基础上求k. 题解:1.5000头牛不是小数目,再怎么也得要n^2的算法,其中,枚举k是需要的,这就有n了,只能想办法给出一个n在O(n)时间内求出最小次数了. 2.对于给定的k,要想O(n)内把次数算出来,即只能扫一遍,一想到的必定是从前往后扫,遇到面朝后的就转头,但这一转牵扯太多,要改太多东西,k一大直接崩溃. 3.对于每次扫描

POJ 1830 开关问题

简单的高斯消元取模,答案为2^自由变元的数量,但是题目的意思把I,J搞反了,坑爹... 开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5425   Accepted: 2023 Description 有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开.你的目标是经过若干次

poj 1830 开关问题 高斯消元

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

POJ 3276 Face The Right Way (常用技巧-尺取法)

[题目链接]:click here~~ [题目大意]:N头牛排成一列1<=N<=5000.每头牛或者向前或者向后.为了让所有牛都 面向前方,农夫每次可以将K头连续的牛转向1<=K<=N,求操作的最少 次数M和对应的最小K. [思路]:由于交换区间翻转顺序对结果没影响,所以从左往右对于需要  翻转的牛进行反转,同时记录对该区间其他牛的影响即cal中的sum, 对于最后部分无法翻转的区间检查是否有反向牛,若有则方案失败.此题思想值得细细思考,常常有一种无限状态,化为有限状态. 代码:

POJ 3276 [Face The Right Way] 题解

题目大意 n头牛排成一行,有的牛面朝前,有的牛面朝后,每一次操作可以使连续的K头牛改变方向:求一个K,使得操作次数最少.输出K以及最少的操作次数.当有多个K满足条件时,输出最小的K. 题目分析 对一个区间来说,多次进行反转操作是没有意义的:另外反转的顺序对结果是没有影响的.所以这道题只需要对所有的可操作区间(即长度为K的区间)考虑是否需要反转. 考虑最左边的牛,当它面朝前时无需反转,当它面朝后时,就反转[1, K]区间一次.然后继续考虑第二头牛即可. 反转的时候不必每头牛都操作一次,只需用一个t

POJ 3276 Face The Right Way 开关问题

Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4367   Accepted: 2025 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 facin

POJ 1830 开关问题 高斯消元,自由变量个数

http://poj.org/problem?id=1830 如果开关s1操作一次,则会有s1(记住自己也会变).和s1连接的开关都会做一次操作. 那么设矩阵a[i][j]表示按下了开关j,开关i会被操作一次,记得a[i][i] = 1是必须的,因为开关i操作一次,本身肯定会变化一次. 所以有n个开关,就有n条方程, 每个开关的操作次数总和是:a[i][1] + a[i][2] + ... + a[i][n] 那么sum % 2就代表它的状态,需要和(en[i] - be[i] + 2) % 2