POJ3276 -- Face The Right Way 反转问题

Face The Right Way
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 5258   Accepted: 2453

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 facing backward, though, and he needs them all to face forward to make his life perfect.

Fortunately, FJ recently bought an automatic cow turning machine. Since he purchased the discount model, it must be irrevocably preset to turn K (1 ≤ K ≤ N) cows at once, and it can only turn cows that are all standing next to each other in line. Each time the machine is used, it reverses the facing direction of a contiguous group of K cows in the line (one cannot use it on fewer than K cows, e.g., at the either end of the line of cows). Each cow remains in the same *location* as before, but ends up facing the *opposite direction*. A cow that starts out facing forward will be turned backward by the machine and vice-versa.

Because FJ must pick a single, never-changing value of K, please help him determine the minimum value of K that minimizes the number of operations required by the machine to make all the cows face forward. Also determine M, the minimum number of machine operations required to get all the cows facing forward using that value of K.

Input

Line 1: A single integer:  N 
Lines 2.. N+1: Line  i+1 contains a single character,  F or  B, indicating whether cow  i is facing forward or backward.

Output

Line 1: Two space-separated integers:  K and  M

Sample Input

7
B
B
F
B
F
B
B

Sample Output

3 3

Hint

For K = 3, the machine must be operated three times: turn cows (1,2,3), (3,4,5), and finally (5,6,7)



问题描述:第一行给出整数n  接下来n行给出B和F 表示面向后方和前方 我们每次可以反转k头牛的转向 求最小的反转策略

使得所有的牛都面向前方(F)。


分析:对于第i头牛,我们考虑要不要反转它 那么就要考虑[i-k+1,i-1] 这些牛的反转策略(因为每次反转k头牛 所以这些牛的反转会导致第i头牛的反转) 如果它们的反转次数为奇数 那么说明第i头牛的转向与起始相反 如果是偶数 则说明第i头牛的转向与起始相反  如果是奇数则说明第i头牛的转向与起始相同。

如果把F编号为0 B编号为1 
那么 若用sum代表前面这些牛的反转总次数 那么 如果sum+dir[i]为奇数 那么一定需要反转 如果为偶数 那么一定不需要反转(每种对应2种情况)

①sum+dir[i]为奇数 只可能是sum为奇数 dir[i]为偶数 此时 说明初始情况牛面向F 而现在与初始情况相反 面向B
或sum为偶数 dir[i]为奇数 此时说明初始情况和现在情况都面向B
都需要反转
②sum+dir[i]为偶数 此时与①相同考虑即可 都不需要反转

那么下一头牛呢?    下一头牛显然只需要把当前的牛反转次数加在sum上 然后把上一个序列的第一头牛的翻转次数去掉即可 中间的都是公共序列 不需要重新计算

最后  如果反转到最后k头牛 还有牛是面向后方的那么就是无解 因为此时再反转k头牛下标已经越界了

代码:



#include 
#include 
#include 
#define MAX_N 5000 + 5
using namespace std;

int dir[MAX_N];
int f[MAX_N];
int n;

int cal(int k)
{
	memset(f,0,sizeof(f));
	int sum = 0; // 前面的反转次数
	int ans = 0; // 反转总次数 
	for(int i =  0;i<=n-k;i++)
	{
		if((sum + dir[i]) % 2 !=0)
		{
			f[i] = 1;
			ans++;
		}
		sum += f[i];
		
		if(i - k +1 >=0)
		{
			sum -= f[i - k + 1];
		}
	}
	for(int i = n-k+1;i<n;i++)
	{
		if((sum + dir[i]) % 2!=0)
		return -1;
		
		if(i - k +1 >=0)
		sum -= f[i-k+1];
	}
	return ans;
}
	void solve()
	{
		int kk = 1, mm = n;
		for(int k = 1;k<=n;k++)
		{
			int m = cal(k);
			if(m >=0 && m <mm)
			{
				mm = m;
				kk = k;
			}
		}
		printf("%d %d\n",kk,mm);
	}
int main()
{
	scanf("%d%*c",&n);
	char c;
	for(int i = 0;i<n;i++)
	{
		scanf("%c%*c",&c);
		if(c == 'F')
		dir[i] = 0;
		else if(c == 'B')
		dir[i] = 1;
	}
	solve();
}


你可能感兴趣的:(杂)