Face The Right Way(反转牛问题)

 题目链接:

http://poj.org/submit?problem_id=3276icon-default.png?t=L9C2http://poj.org/submit?problem_id=3276

题目大意:

 N头牛站成一排,每头牛要么向前要么向后(F表示向前,B表示向后),为了让所有的牛都面向前方,约翰买了一台自动旋转的机器,每次旋转设定一个固定的k值,机器操作一次就旋转连续的k头牛,求出为了让所有牛都面向前方的的最少操作次数m和对应的k值。

思路:

在k确定的情况下,可以只看区间中第一头牛是否需要反转(因为这头牛只能在当前反转,后面的反转不会影响到它),以此确定是否反转,这样就能确定唯一解了。遍历前n-k+1头牛之后,再看剩下的牛是否都是正确方向,如果是,说明当前k能满足题意,否则不能。

所以要对所有的k都求解一次,取对应的m最小值。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <climits>
using namespace std;
const int MAXN = 5005;

// 题目要求计算最小的M和对应最小的K
int N, K, M; // 牛数量,反转长度,反转次数
int dir[MAXN]; // 原本的方向
int tra[MAXN]; // 表示[i, i+K-1]部分的牛反转

// 固定K,返回最小的操作次数M, 无解的话返回-1
int calc(int K){
	memset(tra, 0, sizeof(tra)); // 重置reverse数组
	int res = 0, count = 0; // 总反转次数,当前牛的反转次数
	for(int i=0; i<=N-K; i++){ // 遍历所有可反转位置的头部牛
		if ((dir[i] + count) % 2 != 0) { // 表示需要反转
			res++;
			tra[i] = 1;
		}

		// 更新当前窗口内的count值(为下一次做准备)
		count += tra[i];
		if(i-K+1 >= 0) count -= tra[i-K+1];
	}

	//检查剩下的牛方向是否都正确
	for(int i=N-K+1; i<N; i++){
		if ((dir[i] + count) % 2 != 0) return -1; //方向不正确,无解
		if (i-K+1 >= 0) count -= tra[i-K+1]; //继续维护count的值
	}
	return res; //符合题意,返回结果
}

int main(){
	//快读
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    //输入
	cin >> N;
	for(int i=0; i<N; i++){
		char ch; cin >> ch;
		if(ch == 'B') dir[i] = 1;
		else dir[i] = 0;
	}

	K = 1, M = N;
	for(int k=1; k<=N; k++){
		int m = calc(k);
		if(m >= 0 && m < M){
			//遇到符合题意的更小的m,更新M和对应的k
			M = m;
			K = k;
		}
	}
	printf("%d %d\n", K, M);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值