POJ 3276 Face The Right Way 开关问题

来源:互联网 发布:物流网络存在的问题 编辑:程序博客网 时间:2024/05/18 08:46
反转问题,WA了无数次了,简直欲哭无泪。。技巧是求定长子段和,区间标记。构造定长前缀和函数来判断到第i头牛时该头牛的状态。优化后的代码如下:
/*Memory 144K Time 407MS*/#include <cstdio>#include <iostream>#include <cstring>using namespace std;int N;const int MAXN = 5000;bool dir[MAXN+1], f[MAXN+1];int calc(int K){    memset(f, 0, sizeof(f));    int res = 0;    bool sumi = 0;    int i;    for(i=0; i+K-1<N; i++){        if((sumi+dir[i])%2 != 0){            res++;            f[i] = 1;        }        if(i-K+1 < 0) sumi = (sumi + f[i])%2;        else sumi = (sumi + f[i] - f[i-K+1] + 2)%2;    }    for( ; i<N; i++){        if((sumi+dir[i])%2 != 0){            return -1;        }        sumi = (sumi - f[i-K+1] + 2)%2;    }    return res;}void solve(){    int K = 1, M = N; //放缩    for(int k=1; k<=N; k++){        int m = calc(k);        if(m >= 0 && m < M){            M = m;            K = k;        }    }    printf("%d %d\n", K, M);}int main(){    while(scanf("%d", &N) != EOF){        char ch;        int cnt = 0;        while(cnt < N){            scanf("%c", &ch);            if(ch == 'F') dir[cnt++] = 0;            if(ch == 'B') dir[cnt++] = 1;        }        solve();    }    return 0;}
如果把第一段分成两个for循环写也是可以过的:
for(i=0; i-K+1<0 && i+K-1<N; i++){ //必须加此边界,否则要跪,之前一直都没找出这个bug,WA了好多        if((sumi+dir[i])%2 != 0){            res++;            f[i] = 1;        }        sumi = (sumi+f[i])%2;}    for( ; i+K-1<N; i++){        if((sumi+dir[i])%2 != 0){            res++;            f[i] = 1;        }        sumi = (sumi + f[i] - f[i-K+1] + 2)%2;}
另外,再附上我找这个bug的测试程序
#include <cstdio>#include <iostream>using namespace std;int N;void f1(int K){    int i;    for(i=0; i-K+1<0; i++){        cout<<"a";    }    for( ; i+K-1<N; i++){        cout<<"b";    }    cout<<endl;}void f2(int K){    int i;    for(i=0; i+K-1<N; i++){        if(i-K+1 < 0) cout<<"a";        else cout<<"b";    }    cout<<endl;}int main(){    int K;    cin>>N>>K;    f1(K);    f2(K);    return 0;}



0 0
原创粉丝点击