POJ 3276 反转问题

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;
int n;
int a[5005][2];
int flag[5005];
int fun(int x){
    int sum  = 0;
    int res = 0;

    memset(flag,0,sizeof(flag));
    for(int i = 0;i+x <= n;i++){
        if(sum%2 == 0 && a[i][0] == ‘B‘ || sum % 2 == 1 && a[i][0] == ‘F‘){
            flag[i] = 1;
            res++;
        }
        else{
            flag[i] = 0;
        }
        sum += flag[i];
        if(i+1-x >= 0){
             sum -= flag[i-x+1];
        }
    }
    for(int i = n-x+1;i < n;i++){
        if(a[i][0] == ‘B‘ && sum % 2 == 0 || sum % 2 == 1&& a[i][0] == ‘F‘){
            return -1;
        }
        if(i-x+1 >= 0){
            sum -= flag[i-x+1];
        }
    }
    return res;
}
int main(){
    while(cin >> n){
        for(int i = 0;i < n;i++){
            scanf("%s",a[i]);
        }
        int K = 1;
        int M = n;
        for(int i = 1;i <= n;i++){
            int m = fun(i);
            if(m >= 0&&M > m){
                M = m;
                K = i;
            }
        }
        printf("%d %d\n",K,M);
    }
    return 0;
}

反转问题可以用一个标记记录前面反转的次数,如果当前位置前面反转过偶数次那么这个位置相当于没有反转,如果是奇数次说明反转过了!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-26 13:51:23

POJ 3276 反转问题的相关文章

poj 3276(反转)

传送门:Problem 3276 参考资料: [1]:挑战程序设计竞赛 先献上AC代码,题解晚上再补 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define mem(a,b) (memset(a,b,sizeof(a))) 6 const int maxn=5e3+30; 7 8 int N; 9 int dir[maxn];//0:forw

Face The Right Way POJ 3276(反转)

原题 题目链接 题目分析 由题意可以知道,对于特定的k,同一个区间反转两次是无意义的,考虑能翻第一头牛的区间只有第一个区间,因此第一头牛直接决定是否要翻转第一个区间,然后问题规模减1,同理再对第二头牛进行同样的分析.这里的翻转操作可以用前缀和优化,设f[i]=1表示以第i头牛开始的区间被翻过,f[i]=0则表示没被翻过,则考虑第j头牛时,只需统计前k-1头牛的f值,如果和是奇数则表明第j头牛的朝向与原方向相反,否则相同,最后就可以用O(N)的复杂求求解一个k的最小步骤m,由于所有k都要试一遍,最

反转(开关问题) 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 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 3276 (开关问题)

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

poj 3276 Face The Right Way 递推

地址  http://poj.org/problem?id=3276 解法 依次遍历一次翻转K(1~N)头牛的办法 最后得出转数最小的答案  复杂度是 N*N*N 但是在模拟一次翻转K头牛的时候 我们可以优化模拟翻转的过程 优化效率 如图 当K = 3 每次翻转3头牛的时候 第0头牛 朝后 之前影响到第0头牛的点击数为0 所以我们需要点击1次 将牛朝前 第1头牛 朝后 之前影响第1头牛的点击数为1 所以牛已经朝前不必点击 第2头牛 朝前 之前影响第2头牛的点击数为1 所以需要点击1次  将牛朝前

poj 3276

开关反转问题,想法很巧妙,看了一节课才看懂,严重怀疑自己弱智....就难受 #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn=5000+10; int a[maxn],f[maxn];//B:1,F:0 int n; int fan(int k) { int sum=0,ans=0;