标签:
题目链接:http://poj.org/problem?id=3276
题意:n牛头排成一排,每头牛两个状态,向前或向后,为了让所有的牛都向前,现在有一个机器 每次 能控制连续K头牛转换自己的状态,求让所有牛都向前的最少操作次数,以及对应的K值;
同一头牛翻转的次数为偶数时,相当于没有翻转;我们可以枚举所有的K,看是否能让所有的牛都面向前,当K一定时,先考虑最左端的牛,如果这头牛已经面向前的,无需翻转,否则翻转,
当左到右的操作之后我们就可以不用考虑左端的情况了;我们用f[i]表示区间[i, i+k-1]的牛是否被翻转;(1翻转,0不翻转);
当看第i头牛的状态时,因为第i头牛是和前面k-1头牛的翻转次数总和有关的,所以如果sum( f[i-k+1] 到 f[i-1] )是否为奇数,说明当前状态与初始状态相反,偶数状态不变;
求和的过程可以优化,所以总的时间复杂度为n*n;
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<math.h> using namespace std; #define INF 0x3f3f3f3f #define N 202550 #define PI 4*atan(1.0) #define mod 100000001 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int n, dir[N], f[N]; int solve(int k)///判断连续翻转k头牛是否可行; { met(f, 0);///f[i]表示区间i----i+k-1的牛是否翻转; int sum = 0, cnt = 0;///sum表示当前牛被翻转了多少次,等于前k-1个牛的翻转次数和; for(int i=1; i+k-1<=n; i++) { if((sum+dir[i])%2)///如果当前牛的方向是向后; { f[i] = 1;///翻转i---i+k-1; cnt ++; } sum += f[i]; if(i-k+1>0)///去除之前的影响; sum -= f[i-k+1]; } for(int i=n-k+2; i<=n; i++)///每次都会剩下不足k个(k-1个)的牛,然后检查这些牛的方向是否向前; { if((sum+dir[i])%2)///如果当前牛的方向是向后;说明k值不可以,返回-1; return -1; if(i-k+1 > 0) sum -= f[i-k+1]; } return cnt; } int main() { while(scanf("%d", &n) != EOF) { met(dir, 0);///0向前,1向后; for(int i=1; i<=n; i++) { char s[10]; scanf("%s", s); if(s[0] == ‘B‘) dir[i] = 1; } int K = 1, Min = n; for(int k=1; k<=n; k++) { int ans = solve(k); if(ans == -1) continue; if(ans < Min) { Min = ans; K = k; } } printf("%d %d\n", K, Min); } return 0; }
Face The Right Way---hdu3276(开关问题)
标签:
原文地址:http://www.cnblogs.com/zhengguiping--9876/p/5790828.html