完美的代价
题目:http://www.tsinsen.com/A1043
所用的是贪心算法,如果让第一个位置用最小步数达到,那么就是找和第一个位置相同的字母,并且这个字母距离的最后一个位置最近。asmaasm,那么就将最后一个a冒泡到m后面。
第二个字母也是这样,最后一直整完,我先判断的是否能形成回文。如果是基数,那么我的算法会先让改点不动,弄完daass->dassa之后再将d归位。
伪代码:
1)判断是否形成回文;//不形成输出impossible并且退出
2)for(i=0;i<j;i++)//形成回文
j=n-coun-i;//coun探测到有个基数字母后,后半段与前半段对应的字母位置就变化了,反映在coun上,初始为1
在i到j之间找到与i相同的字母k
如果i=k说明是基数字母,不动他,coun=0,记录位置position。
如果i!=k那么两两对换直到k换到j的位置。想象成k冒泡到j,并且更新step。
if(position==-1)//未被修改
将所记录的position位置的换到j之前并且更新step。
#include <iostream> #include <math.h> using namespace std; char s[8003]; int n; bool po() { bool flag=false; int abc[27]; for(int i=0; i<27; i++) abc[i]=0; for(int i=0; i<n; i++) { int u=s[i]-'a'; abc[u]++; } for(int i=0; i<26; i++) { if(abc[i]%2!=0&&flag==false) { flag=true; } else if(abc[i]%2!=0&&flag==true) { cout<<"Impossible"<<endl; return false; } } return true; } int main() { int step=0; cin>>n; cin>>s; int uniqu=-1; int coun=1; int i=0; int j=n-coun-i; if(po()) { for(i=0; i<j; i++) { j=n-coun-i; if(s[i]!=s[j]) { int j2=j; while(j2!=i&&s[j2]!=s[i]) j2--; if(j2==i) { uniqu=i; coun=0; } else { step=step+j-j2; for(int k=j2; k<j; k++) swap(s[k],s[k+1]); } } } if(uniqu!=-1) { for(int k=uniqu; k<j-1; k++) swap(s[k],s[k+1]); step=step+j-uniqu-1; } cout<<step<<endl; //cout<<s<<endl; } return 0; }
本博客专注于错误锦集,在作死的边缘试探