Time limit1000 ms Memory limit1048576 kB OSLinux SourceIDI-Open 2016
Anna and Bob are having a baby. They both enjoy the advantage of having palindrome names, meaning that their names are spelled the same way forwards and backwards. Wanting to be good parents, they decide to give their child a palindrome name too. The only problem is that they aren’t sure if the one they picked is a palindrome. If it turns out it isn’t a palindrome, they want to change it to a palindrome using as few changes as possible. The allowed changes are:

Change one letter of the name.

Add a letter to the end of the name.

Help Bob and Anna find out how many changes they need to make to the name to make it a palindrome.

Input

Input is the name they have chosen.

Output

Output the number of changes they need to make.

Limits

The length of the name is at least 1 and at most 100 characters.

The name consists of only lowercase letters a–z.

Sample Input 1 Sample Output 1
kaia
1
Sample Input 2 Sample Output 2
abcdefgded
4

题意:给你一个字符串(只由’a’-‘z’组成),有两种操作:1.在尾部添加 2.改变一个字符
问最少多少步操作能使它变成回文串?

在训练赛时,之前做过这样的题,没分析时间复杂度,然后想着不能首尾分别比较,一直比吧?
然后训练结束后,听同学说可以这样写,, 瞬间懵逼。。
仔细看题,字符串最长为100,最多只用比较50次,1s计算10^7次的问题应该不是很大,或者可以卡过

所以说这种做法并不是暴力的,, 好吧,暴力也行,AC了就好

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
char str[102];
int num[102];
int judge(int i,int j)///比较首尾是否相同
{
    int cnt=0;
    while(i<j)
    {
        if(str[i]!=str[j-1])
            cnt++;
        i++;j--;
    }
    return cnt;
}
int main()
{
    while(~scanf("%s",str))
    {
        int MIN;
        int len=strlen(str);
        for(int i=0; i<len/2; i++)
            num[i]=i+judge(i,len);
        MIN=num[0];///MIN取其中最小值
        for(int i=1;i<len/2;i++)
        {
            MIN=min(MIN,num[i]);
        }
        printf("%d\n",MIN);
    }
    return 0;
}

同学写的结题报告中把在尾部添加想成一个和已知串相反的串移动的步数,这个思想转换比较好。。
例:k a i a
a i a k 挪位数:0 字符不同个数:4 (由于对称关系,我们只需改变两个字符即可达到回文效果)
需改变字符数:4/2=2 首次答案:(挪位数)0+(需改变字符数)2=2
k a i a
a i a k 挪位数:1 字符不同个数:0
需改变字符数:0 第二次答案:1+0=1
k a i a
a i a k 这里已经可以不用处理,对于长度为L的字符串我们改变其中一半必然能达到回文效果
故该字符串最小操作数为:1

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int main()
{
    char ch[105];
    while(scanf("%s",ch)!=EOF)
    {
        int l,ans,sum;
        l=strlen(ch);
        ans=l/2;
        for (int t=0;t<l;t++)                        /* t表示挪位数,这里还可修改,挪位数只需判断到字符串长度一半加一即可 */
        {
            int x1,x2;                               /* x1,x2为首位下表,用于比较 */
            x1=t;
            x2=l-1;
            sum=t;                                   /* sum记录当前方式操作次数 */
            while(x1<l)
            {
                if (ch[x1]!=ch[x2]&&x1<x2) sum++;    /* 因为对称关系,我们只需计算前一半 */
                x1++;
                x2--;
            }
            if (sum<ans) ans=sum;                    /* 变更最小操作数 */
        }
        printf("%d\n",ans);
    }
    return 0;
}