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
Because FJ must pick a single, never-changing 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頭牛為最左端所在的區間需要反轉。
令,表示第i頭牛前反轉的區間對第i頭牛的影響,若sum為奇數,則第i頭牛與最開始的朝向相反,若sum為偶數,則第i頭牛與最開始的朝向相同。
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;
}