uva10716 Evil Straw Warts Live

27 篇文章 0 订阅

很遗憾这道题又不是完全自己想出来的。不过我要仔细的分析下我的思维过程,希望以后能逐渐优化。

开始看题,觉得要用贪心,感觉可以从中间往两边处理,但想不出严密的证明,其实后来才知道一开始就想错了。

还没完全想清楚的时候,我就开始写代码,写到一半发现问题,如果同一个字母在序列的同一边时,无论怎样移动这两个字母,移动之后序列的中心会改变,也就是另一半会多一个,到这里时我就进死胡同了,一直在想怎么解决这个问题,却一直没有好的办法。。。。就这样,我去看了题解。原来别人都是从两边往中间处理的。想了下,这样确实妙,因为每次移动之后,剩下中间的字母的移动范围都变小了,而且不用担心会改变序列的中心,于是开始重新写。可这里我又犯了个错,我没完全摆脱之前的思路,在遇到奇数长度序列时,先把该字母移动到中间,这样看似没问题,其实当之后处理时,如果还存在偶数个这个字母,可能就会移动这个中心字母到外围。。。这又时一处思维不严密。。

其实在遇到死胡同的时候,我就应该反思自己想得是不是有问题,甚至在一开始,我就应该意识到从两边处理会更好。一方面,自己舍不得已经写出来的代码,实际上我转换思路后没用多长时间就写出来了,而且代码也很短。好的意识,好的思路,绝对比打字的速度重要。。。。另一方面,还是尽量能不动脑经就不懂脑筋的习惯,或者叫潜意识。。。。。菜鸟啊,你什么时候能争点气

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 110
using namespace std;

char s[MAX],map[26];
int len,all;

void swap(char &i,int &j)
{
    char t;
    t=i,i=j,j=t;
}

void moveto(int a,int b)
{
    int i,j;
    if(a<b)
    {
        for(i=a;i<b;i++)
        {
            swap(s[i],s[i+1]);
            all++;
        }
    }
    else if(a>b)
    {
        for(i=a;i>b;i--)
        {
            swap(s[i],s[i-1]);
            all++;
        }
    }
    //printf("move%d %d to %d\n",all,a,b);
}

int main()
{
    int t,i,j,js,which,a,b;
    scanf("%d",&t);
    while(t--)
    {
        memset(map,0,26);
        scanf("%s",s);
        len=strlen(s),js=0,all=0;
        for(i=0;i<len;i++)
            map[s[i]-'a']++;
        for(i=0;i<26;i++)
            if(map[i]%2==1)
            {
                js++;
                which=i;
            }
        if(len%2==0&&js!=0||len%2==1&&js!=1)
        {
            printf("Impossible\n");
            continue;
        }
        /*if(len%2==1)
        {
            if(s[len/2]!=which+1)
            {
                for(a=len/2-1,b=(len-1)/2+1;a>=0&&b<len;a--,b++)
                {
                    if(s[a]==which+'a')
                    {
                        moveto(a,(len-1)/2);
                        break;
                    }
                    if(s[b]==which+'a')
                    {
                        moveto(b,(len-1)/2);
                        break;
                    }
                }
            }
        }*/
        for(a=0,b=len-1;a<=len/2&&b>=(len)/2&&a<=b;a++,b--)
        {
            if(s[a]==s[b])
                continue;
            for(i=b-1;s[i]!=s[a]&&i>=a;i--);
            for(j=a+1;s[j]!=s[b]&&j<=b;j++);
            if(i-a>b-j)
                moveto(i,b);
            else
                moveto(j,a);
        }
        printf("%d\n",all);
    }
    return 0;
}



























/*#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 110
using namespace std;

char s[MAX],map[30];
int all,a,b,targeta,targetb,len;

void swap(char &i,int &j)
{
    char t;
    t=i,i=j,j=t;
}

void moveto(int a,int b)
{
    int i,j;
    if(a<b)
    {
        for(i=a;i<b;i++)
        {
            swap(s[i],s[i+1]);
            all++;
        }
    }
    else if(a>b)
    {
        for(i=a;i>b;i--)
        {
            swap(s[i],s[i-1]);
            all++;
        }
    }
    //printf("move%d %d to %d\n",all,a,b);
}

int find(int index)
{
    int i,j,cur,temp,small=MAX;
    for(cur=a-1;cur>=0;cur--)
    {
        if(s[cur]==s[index])
        {
            temp=index-cur-1+b-a-1;
            if(temp<small)
            {
                small=temp;
                if(index==a)
                    targeta=cur;
                else
                    targetb=cur;
            }
        }
    }
    for(cur=b+1;cur<len;cur++)
    {
        if(s[cur]==s[index])
        {
            temp=cur-b;
            if(temp<small)
            {
                small=temp;
                if(index==a)
                    targeta=cur;
                else
                    targetb=cur;
            }
        }
    }
    return small;
}

int main()
{
    int t,i,j,js,which,smalla,smallb;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        len=strlen(s);
        js=all=0;
        memset(map,0,30);
        for(i=0;i<len;i++)
            map[s[i]-'a']++;
        for(i=0;i<26;i++)
        {
            if(map[i]%2==1)
            {
                js++;
                which=i;
            }
        }
        if(len%2==0&&js!=0||len%2==1&&js!=1)
        {
            printf("Impossible\n");
            continue;
        }
        if(len%2==1)
        {
            for(i=0;i<len;i++)
            {
                if(s[i]==which+'a')
                {
                    moveto(i,(len-1)/2);
                    break;
                }
            }
        }
        //printf("teat");
        for(a=len/2-1,b=(len-1)/2+1;a>0&&b<len-1;a--,b++)
        {//printf("teat");
            //printf("b %d %d all%d s%s\n",s[a],s[b],all,s);
            if(s[a]==s[b])
                continue;
            smalla=find(a);
            smallb=find(b);
            printf("a%d %d\n",smalla,smallb);
            if(smalla<smallb)
            {
                if(targeta<a)
                {
                    moveto(targeta,a-1);
                    moveto(a,b-1);
                }
                else
                    moveto(targeta,b);
            }
            else
            {
                if(targetb>b)
                {
                    moveto(targetb,b+1);
                    moveto(b,a+1);
                }
                else
                    moveto(targetb,a);
            }
        }
        printf("%d\n",all);
    }
    return 0;
}*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值