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 }