http://poj.org/problem?id=3276
Sample Input
7 B B F B F B B
Sample Output
3 3
穷举肯定是要超时的 2^n个状态...但是先思考一些规律吧:
1、转动奇数次,必然与初始方向相反;
2、转动偶数次,必然与初始方向相同;
枚举k:1-n,得到O(n^3)的代码:(这个代码会超时,只是模拟而已)
//TLE O(n^3) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define MAXN 5005 int s[MAXN]; int n; int test(int k) { int i,j,ans=0; for(i=0;i<n-k+1;i++) { if(!s[i]) { for(j=i;j<i+k;j++) { s[j]=!s[j]; } ans++; } } for(j=i;j<n;j++) if(!s[j]) return -1; return ans; } int main() { int i,len,kmin,m,mmin,k; char cow[MAXN]; while(scanf("%d",&n)!=EOF) { memset(s,0,sizeof(s)); mmin = MAXN; m=-1; for(i=0;i<n;i++) { scanf("%c",&cow[i]); if(cow[i]=='\n') i--; } cow[i]='\0'; for(k=1;k<=n;k++) { for(i=0;i<n;i++) { if(cow[i] == 'F') s[i]=1; else s[i]=0; } m=test(k); /////////////// //printf("m=%d\n",m); /////////////// if(m>=0&&m<mmin) { kmin=k; mmin=m; } } printf("%d %d\n",kmin,mmin); } return 0; }
f[i] 表示从i-k+1到i头牛的反转情况,值为1表示反转,值为0表示没有反转
那么sum=f[i-k+1]+f[i-k+2]+...+f[i-1],如果sum为基数,那么转动奇数次,必然与初始方向相反,如果sum为偶数,必然与初始方向相同。
于是省去一重循环,得到O(n^2)的代码 AC
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define MAXN 5005 int s[MAXN]; int f[MAXN]; int n; int test(int k) { int i,j,ans=0,sum=0; memset(f,0,sizeof(f)); for(i=0;i<n-k+1;i++) { if((sum)%2 == 1) { if(s[i]) { ans++; f[i]=1; } } else { if(!s[i]) { ans++; f[i]=1; } } sum+=f[i]; if(i-k+1>=0) sum-=f[i-k+1]; } for(i=n-k+1;i<n;i++) { if(sum%2) { if(s[i]) return -1; } else { if(!s[i]) return -1; } if(i-k+1>=0) sum-=f[i-k+1]; } //if(!s[i]) // return -1; return ans; } int main() { int i,len,kmin,m,mmin,k; char cow[MAXN]; while(scanf("%d",&n)!=EOF) { memset(s,0,sizeof(s)); mmin = MAXN; m=-1; for(i=0;i<n;i++) { scanf("%c",&cow[i]); if(cow[i]=='\n') { i--; continue; } if(cow[i] == 'F') s[i]=1; else s[i]=0; } cow[i]='\0'; for(k=1;k<=n;k++) { m=test(k); if(m>=0&&m<mmin) { kmin=k; mmin=m; } } printf("%d %d\n",kmin,mmin); } return 0; }