完美的代价

题目: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;

}

  

    

posted @ 2017-01-22 22:13  甜豆儿  阅读(304)  评论(0编辑  收藏  举报