题意
N头牛排成一列1<=N<=5000。每头牛或者向前(表示为F)或者向后(表示为B)。为了让所有牛都面向前方,农夫每次可以将K头连续的牛转向1<=K<=N,求操作的最少次数M和对应的最小K。
思路
首先满足操作次数最小,然后求最小操作长度。
第i位是否反转可以根据前[i-k+1,i-1]判断,所以维护一个sum[i-k+1,i-1],枚举操作长度k,求解。
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <iostream> #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <map> #include <set> using namespace std; #define NV 100005 #define ll long long int n,a[5050],f[5050]; int work(int k){ memset(f,0,sizeof(f));int ret=0,sum=0; for (int i= 1 ; i <= n - k +1 ; i++){ ret += (a[i]+sum)&1; f[i] = (a[i]+sum)&1; sum += f[i]; if(i - k + 1 >= 1)sum -= f[i - k + 1]; } for(int i= n+2-k ;i <=n ; i++){ if((a[i]+sum) &1 ) return -1; if(i - k + 1 >= 1)sum -= f[i - k + 1]; } return ret; } void solve(){ int K = 1 , M = n,ret; for(int k = 1 ; k <= n ; k++){ ret = work(k); if(ret >= 0 && ret < M){ K = k; M = ret; } }printf("%d %d\n",K,M); } int main(){ cin>>n;char c; for(int i=1 ; i<=n ;i++ ){ getchar();c=getchar(); a[i] = c=='B' ? 1 : 0; } solve(); return 0; }
|