poj3276Face The Right Way

题目链接: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\n",ansk,ansm);
54 
55     }
56 }

 


posted @ 2017-03-21 16:28  yijiull  阅读(98)  评论(0编辑  收藏  举报