1. 程式人生 > >POJ3276 Face The Right Way(開關問題)

POJ3276 Face The Right Way(開關問題)

題目連結

Face The Right Way

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 6823 Accepted: 3166

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頭牛排成了一列。每頭牛頭向前或向後。為了讓所有的牛都面向前方,農夫約翰買了一臺自動轉向的機器。這個機器在購買時就必須設定一個數值K,機器每操作一次恰好使K頭連續的牛轉向。求讓所有牛都能面向前方需要的最少操作次數M和對應的最小的K.

1、交換區間反轉的順序對結果是沒有影響的。

2、對同一個區間進行兩次以上的反轉是多餘的。

考慮最左端的牛,包含這頭牛的區間只有一個,如果這頭牛面朝前方,則這個區間不需要反轉;如果這頭牛面朝後方,則這個區間需要反轉,而且在此之後這個最左的區間就不需要再考慮了。通過首先考慮最左端的牛,問題的規模就縮小了1。如此重複下去每次判斷最左端的牛。

令f[i]=1表示第i,i+1,i+2……,i+k-1頭牛即第i頭牛為最左端所在的區間需要反轉。

sum=\sum_{j=i-k+1}^{i-1}f[j],表示第i頭牛前反轉的區間對第i頭牛的影響,若sum為奇數,則第i頭牛與最開始的朝向相反,若sum為偶數,則第i頭牛與最開始的朝向相同。

\sum_{j=i-k+2}^{i}f[j]=\sum_{j=i-k+1}^{i-1}f[j]+f[i]-f[i-k+1]

AC程式碼:

#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#define e 2.71828182
#define Pi 3.141592654
using namespace std;
int N,f[5010];//f[i]為1表示第i,i+1,i+2,,,i+k-1頭牛都反轉 
char cow[5010];
int fun(int k)
{
	memset(f,0,sizeof(f));
	int ans=0;//反轉的次數 
	int sum=0;
	//第i頭牛是否需要翻轉與它本身的狀態和f[i-k+1],f[i-k+2],,,f[i-1]有關 
	for(int i=1;i<=N-k+1;i++)
	{
		if(sum%2==0&&cow[i]=='B')//前面的翻轉並沒有改變第i頭牛的轉向 
			f[i]=1,ans++; 
		else if(sum%2==1&&cow[i]=='F')//前面的翻轉改變了第i頭牛的轉向 
		    f[i]=1,ans++;
		
		sum+=f[i];
		if(i-k+1>=1) sum-=f[i-k+1];
	}
	//第N-k+2頭牛之後不能再反轉了,判斷剩下的牛朝向是否滿足條件 
	for(int i=N-k+2;i<=N;i++)
	{
		if(sum%2==0&&cow[i]=='B') return -1;//不滿足則返回-1 
		else if(sum%2==1&&cow[i]=='F') return -1;
		
		sum+=f[i];
		if(i-k+1>=1) sum-=f[i-k+1];
	}
	return ans;
}
int main()
{
	cin>>N;
	for(int i=1;i<=N;i++) cin>>cow[i];
	
	int k=1<<30,m=1<<30;
	for(int i=1;i<=N;i++)//一次使連續的i頭牛轉向 
	{
		if(fun(i)>=0&&fun(i)<m)
		k=i,m=fun(i);
	}
	cout<<k<<' '<<m;
}