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;//sum是待反转的数量
    memset(f,0,sizeof(f));
    for(int i=0;i+k<=n;i++)//注意这里是<=n,目的是预定最后一次反转
    {
        if((sum+a[i])%2!=0)//最神奇的式子,只有出现要被反转的牛才成立,与sum-=f[i-k+1]呼应更新
        {
            f[i]=1;//预定反转
            ans++;
        }
        sum+=f[i];
        if(i-k+1>=0)
        sum-=f[i-k+1];//反转,当然,只有f[i-k+1]=1才行,否则没什么卵用
    }
    for(int i=n-k+1;i<n;i++)
    {
        if((sum+a[i])%2!=0)//最后反转一次后还需要再反转,就不成立了
            return -1;
            if(i-k+1>=0)
        sum-=f[i-k+1];
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        char cc;
        cin >> cc;
        if(cc==‘B‘) a[i]=1;
        else a[i]=0;
    }
    int k=1,m=n;
    for(int i=1;i<=n;i++)
    {
       int mm=fan(i);
       if(mm>=0&&mm<m)//更新最小次数
       {
           m=mm;
           k=i;
       }
    }
    printf("%d %d\n",k,m);
    return 0;
}
时间: 2024-10-06 19:20:58

poj 3276的相关文章

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

传送门: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

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 &am

POJ 3276 The Cow Lexicon DP-字符串匹配

点击打开链接 The Cow Lexicon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8325   Accepted: 3934 Description Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no more 25 of the characters 'a'..'z'.