题目链接:http://poj.org/problem?id=3276
参考别人的。
详解见注释。
牛F代表朝前,B代表朝后
每次操作可以使连续的K头牛改变朝向,求操作次数m最小的情况下的最小k
枚举K,求m,不断更新。
用数组记录每个牛相对前一头牛的朝向,0为朝向相同,1为相反
每次操作实际只改变了两头牛相对前一头牛的朝向
1 #include<cstdio>
2 #include<cstring>
3 const int maxn=5010;
4 int po[maxn],temp[maxn];
5 int n;
6 char pre='F',now;
7
8 int main()
9 {
10 while(scanf("%d",&n)!=EOF)
11 {
12 int ansk=0,ansm=1e9;
13 for(int i=1;i<=n;i++) //第i头牛与第i-1头牛朝向相同时,po[i]为0,相反时为1。此处虚拟第0头牛朝向为前。
14 {
15 getchar();
16 scanf("%c",&now);
17 if(now==pre) po[i]=0;
18 else po[i]=1;
19 pre=now; //更新前一个节点
20 }
21 for(int k=1;k<=n;k++) //枚举翻转长度
22 {
23 memcpy(temp,po,sizeof(po));
24 int ct=0;
25 int ok=1;
26 /*
27 // 方便理解
28 //每次更新区间(i,i+k-1),实际上只改变了第i头和第i+k头牛相对前一头牛的关系
29 for(int i=1;i+k-1<=n;i++) if(temp[i])
30 {
31 temp[i]^=1;
32 temp[i+k]^=1;
33 ct++;
34 }
35 for(int i=1;i<=n;i++) if(temp[i]) //如果有朝向为后的则失败
36 {ok=0;break;}
37 */
38 //下面是优化版
39 int i;
40 for(i=1;i+k-1<=n;i++) if(temp[i])
41 {
42 temp[i+k]^=1;
43 ct++;
44 }
45 for(;i<=n;i++) if(temp[i])
46 {ok=0;break;}
47 if(ok&&ansm>ct) //更新答案
48 {
49 ansk=k;
50 ansm=ct;
51 }
52 }
53 printf("%d %d
",ansk,ansm);
54
55 }
56 }