uva 10152 ShellSort

来源:互联网 发布:mac运行windows过热 编辑:程序博客网 时间:2024/05/21 07:02

这道题我是用链表来解决的,首先把字符串的序列抽象成整数的序列,将字符串按照最后要求出现的顺序从1到n编号,然后将号数和字符串的对应关系保存在两个map中,得出一开始在初始情况下的字符串的序号序列a,这样问题就变成了怎么按照题目的移动方式把序列a变成序列(1,2,3,4,5......n),观察一下测试数据中给出的移动方法,可以分析一下移动的过程,首先最后的序列是递增的,所以在进行移动的时候,肯定会将那些小于其前面的某些元素的元素往最前面移动,当然符合这种条件的元素可能有多个,只要找出最大的一个往最前面移动就行了,因为题目要求移动的次数最小,所以先移动数值大的元素到最前面,然后去移动数值小的元素,那么数值小的元素自然就排在数值大的前面了,这样最后得出的序列才是从1到n递增的,当找不到这样的元素的时候,说明已经完成了移动的工作了。但是这样做效率有点低,请高手指教更好的方法。

下面是手算的两个例子:

下面是代码:

#include <stdio.h>#include <map>#include <string>#include <string.h>#include <list>#include <iostream>using namespace std;char name[210][100];char buffer[100];typedef string NAME;typedefintINDEX;map<NAME,INDEX> map_name_index;map<INDEX,NAME> map_index_name;int a[210]; //a[i]是一开始的序列,目标是得到序列1,2,3,4,5,....,nvoid func(int n){//printf("result:\n");int i, max; list<int> l;list<int>::iterator it_i, it_j, it_max;bool f;for(i=1; i<=n; i++)l.push_back(a[i]);while(1){f = false;max = -1;for(it_i=++l.begin(); it_i!=l.end(); it_i++){if(*it_i > max)for(it_j=l.begin(); it_j!=it_i; it_j++){if(*it_j > *it_i){max = *it_i;it_max = it_i;f = true;break;}}}if(!f)break;cout << map_index_name[max] << endl;l.push_front(max);l.erase(it_max);}printf("\n");}int main(void){int N, n;int i;string str;scanf("%d", &N);getchar();while(N--){map_name_index.clear();map_index_name.clear();scanf("%d", &n);getchar();for(i=1; i<=n; i++)gets((char*)(name+i));for(i=1; i<=n; i++){gets(buffer);str.assign(buffer, strlen(buffer));map_index_name[i] = str;map_name_index[str] = i;}for(i=1; i<=n; i++){str.assign((char*)(name+i), strlen((char*)(name+i)));a[i] = map_name_index[str];}func(n);}return 0;}