“推恩令”——分治法

来源:互联网 发布:微商拍小视频软件 编辑:程序博客网 时间:2024/06/10 12:45

A-01 POJ1854

A palindrome is a string of symbols that is equal to itself when reversed. Given an input string, not necessarily a palindrome, compute the number of swaps necessary to transform the string into a palindrome. By swap we mean reversing the order of two adjacent symbols. For example, the string "mamad" may be transformed into the palindrome "madam" with 3 swaps:swap "ad" to yield "mamda"swap "md" to yield "madma"swap "ma" to yield "madam"

Input
The first line of input gives n, the number of test cases. For each test case, one line of input follows, containing a string of up to 8000 lowercase letters.
Output
Output consists of one line per test case. This line will contain the number of swaps, or “Impossible” if it is not possible to transform the input to a palindrome.
Sample Input

3mamadasflkjaabb

Sample Output

3Impossible2

这道题目的大致意思就是任意给你一个长度不超过8000的小写字符串,可以交换任意两个相邻的(adjacent)字母,要你用最少的交换次数使这个字符串是回文(palindrome)。
这是一道基本的分治题,算法思路就死从两头开始比较,如果两个字母不同,就从除去两头已经符合条件的中间一串字符中寻找能够与两端交换的字母,分别从左右两段开始找,判断两遍那个次数少,然后操作一遍,挨个交换(attention!!!);如果相同就向下扩大左右两段子串范围;
需要注意的是,以上步骤开始之前,可以判断一下是否有多个字母的个数是奇数个,如果有,那么就直接“Impossible”;
下面贴代码:

#include <algorithm>#include <bitset>#include <cassert>#include <climits>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <deque>#include <iomanip>#include <iostream>#include <map>#include <numeric>#include <queue>#include <set>#include <stack>#include <string>#define INF 0x3f3f3f3f#define EPS 1e-6using namespace std;unsigned long len;bool check(int ch[]){    int flag=0;    for(int i=0;i<26;i++){        if(ch[i]%2==1)flag++;    }    if(flag>1)return true;    else return false;}int divide(string a,int left,unsigned long right){    int i=left,j=(int)right;    int suml=0,sumr=0,sum=0;    while(i<j){        int l,r;        for(l=i;l<j;l++)            if(a[l]==a[j]){suml=l-i;break;}        for(r=j;r>i;r--)            if(a[r]==a[i]){sumr=j-r;break;}        if(l-i<j-r){            sum+=suml;            for(int k=l-1;k>=i;k--){                char tmp;                tmp=a[k];a[k+1]=a[k];a[k+1]=tmp;            }        }        else {            sum+=sumr;            for(int k=r+1;k<=j;k++){                char tmp;                tmp=a[k];a[k-1]=a[k];a[k-1]=tmp;            }        }        i++;j--;        suml=0;sumr=0;    }    return sum;}int main(){    int n;    cin>>n;    while(n--){        int ch[26];        memset(ch,0,sizeof(ch));        string a;        cin>>a;        len=a.size();        for(int i=0;i<a.size();i++){            ch[a[i]-'a']++;        }        if(check(ch)){cout<<"Impossible"<<endl;continue;}        else cout<<divide(a,0,len-1)<<endl;    }    return 0;}继续刷题!!!
0 0