链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3076
题意:
对于一个升序的排列1~n(1≤n≤300),用不超过2n^2次操作把它变成给定的排列。
操作只有两种:交换前两个元素(操作1);把第一个元素移动到最后(操作2)。
分析:
可以对给定的排列做个映射,然后将问题转换为:
对于给定的一个1~n(1≤n≤300)的排列,用不超过2n^2次操作把它变成升序。
然后用冒泡排序的思想即可。
代码:
1 #include <cstdio> 2 #include <deque> 3 #include <algorithm> 4 using namespace std; 5 6 int cor[300+5]; 7 deque<int> Q; 8 9 void shift(){ //操作2 10 Q.push_back(Q.front()); 11 Q.pop_front(); 12 printf("2"); 13 } 14 15 void change(){ //操作1 16 swap(Q[0], Q[1]); 17 printf("1"); 18 } 19 20 int main(){ 21 int n; 22 while(scanf("%d", &n) && n){ 23 Q.clear(); 24 for(int x, i = 0; i < n; i++){ 25 scanf("%d", &x); 26 cor[x] = i + 1; 27 Q.push_back(x); 28 } 29 for(int i = 0; i < n; i++) Q[i] = cor[i+1]; //对给定的排列做映射 30 31 int cur = n, p = find(Q.begin(), Q.end(), n) - Q.begin(); //cur是当前调整的数字,p指向该位置 32 for(; Q[p] == Q[(n+p-1)%n] + 1; p = (n+p-1)%n) cur--; //若当前数字已经安排到正确的相对位置,则跳过 33 if(cur == n) cur--; //跳过第一个,因为它已经到了正确的相对位置 34 35 while(cur > 0){ 36 while(Q[0] != cur) shift(); 37 while(Q[0] > Q[1]){ 38 change(); 39 if(cur > 2) shift(); 40 } //将当前调整的数字移到Q[0],并且其后面的数字是Q[0]+1 41 cur--; 42 for(p = 0; Q[p] == Q[(n+p-1)%n] + 1; p = (n+p-1)%n) cur--; 43 } 44 while(Q[0] != 1) shift(); 45 printf("\n"); 46 } 47 return 0; 48 }