题目

给定n和k,输出用SJT算法生成的第k个排列。其中,第一个排列为1,2,3,…,n。
输入:一行两个整数n,k。
输出:一行用空格隔开的n个数,是SJT算法生成的第k个排列。
数据规模与约定:①保证存在第k个排列;②对所有数据,n<=10;③时间限制为1s,空间限制为512MB。
Sample Input: 5 23
Sample Output: 4 1 5 3 2

SJT算法

初始状态为“向量”1,2,3,…,n(统一朝左)。
①找到最大的可移动数m(只要一个数m指向比它小的数,那么数m就可以移动)。
②将m与被m指向的数交换位置。
③比m大的数方向要改变,比m小的数方向不变。
④重复上述步骤,直到找不出最大可移动数为止。

思路

单纯套用SJT模板

代码

正确代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
int main()
{int n,k;scanf("%d%d",&n,&k);vector<int>a(n+1);for(int i=1; i<=n; i++) a[i]=i; //第一轮初始是1-nvector<int>d(n+1);for(int i=1; i<=n; i++) d[i]=-1; //方向全部朝左,每个数可以按照它的方向移动一步for(int r=1; r<=k-1; ++r) //第一轮已经结束,要找第k轮结果,还要进行k-1轮{int mobile_int=0;//目前最大可移动数int pos=0;//这个可移动数的位置for(int i=1; i<=n; i++)//寻找最大可移动数{int j=i+d[i];//将要走到的位置if(j==0||j>n||a[j]>a[i]) continue;//不能到最左边边界,也不能到最右边边界,一个数不能跨过比它大的数if(a[i]>mobile_int){mobile_int=a[i];pos=i;}}int tpos=pos+d[pos];//可移动数的下一步的位置swap(a[pos],a[tpos]);//交换数字swap(d[pos],d[tpos]);//交换方向for(int i=1; i<=n; i++){if(a[i]>mobile_int) d[i]=-d[i];//大于最大可移动数的数a[i]的方向d[i]要取反}}for(int i=1; i<n; ++i){printf("%d ",a[i]);}printf("%d\n",a[n]);return 0;
}

网上模板
PS:不知道为啥要写那么复杂。。。可能是要照顾到全部数据???

//邻位对换法
void exchange(int length){Item * data = (Item *)malloc(sizeof(Item) * length);int index, indexOfMax;for (index = 0; index < length; ++index){data[index].digit = index + 1;//初始化data[index].direction = -1;//定义初始方向(全部向左)data[index].mobile = (index != 0) ? 1 : 0;}indexOfMax = length - 1;FILE * fp = fopen("exchange.txt", "w");exPrint(data, length, fp);while (1== data[indexOfMax].mobile || existMobile(data, length)){if (1== data[indexOfMax].mobile){int direction = data[indexOfMax].direction;exSwap(data, indexOfMax, indexOfMax+direction);indexOfMax += direction;if ((indexOfMax == 0 && direction == -1) || (indexOfMax == length-1 && direction == 1)){toMobileorNot(data, length);}} else{index = findMax(data, length);if (index == -1)break;int direction = data[index].direction;exSwap(data, index, index + direction);index += direction;changeDirection(data, length, index);toMobileorNot(data, length);}exPrint(data, length, fp);}fclose(fp);free(data);
}
int existMobile(Item data[], int length){//判断是否存在可移动数int index;for (index = 0; index < length; ++index){if (data[index].mobile == 1)return 1;}return 0;
}
int findMax(Item data[], int length){//找到最大的可移动数int ans = -1;for (int index = 0; index < length; ++index){if (data[index].mobile == 1){if (ans == -1)ans = index;else if (data[index].digit > data[ans].digit)ans = index;}}return ans;
}
void changeDirection(Item data[], int length, int index){//改变大于可移动数的数的方向for (int i = 0; i < length; ++i){if (data[i].digit > data[index].digit){data[i].direction = -data[i].direction;}}
}
void toMobileorNot(Item data[], int length){if (data[0].direction == 1 && data[0].digit > data[1].digit)data[0].mobile = 1;elsedata[0].mobile = 0;for (int i = 1; i < (length - 1); ++i){int direction = data[i].direction;if (data[i].digit > data[i+direction].digit)data[i].mobile = 1;elsedata[i].mobile = 0;} if (data[length-1].direction == -1 && data[length-1].digit > data[length-2].digit)data[length-1].mobile = 1;elsedata[length-1].mobile = 0;
}
void exPrint(Item data[], int length, FILE * fp){//输出for (int index = 0; index < length; ++index){fprintf(fp, "%d ", data[index].digit);}fprintf(fp, "\n");
}
void exSwap(Item data[], int i, int j){//交换两个数的位置Item tmp = data[i];data[i] = data[j];data[j] = tmp;
}

SJT生成排列(清华OJ)相关推荐

  1. 生成排列 --- 蛮力法,Johnson-Trotter算法

    生成排列 --- 蛮力法,Johnson-Trotter算法 蛮力法 Johnson-Trotter算法 蛮力法 思路: 通过递归遍历所有的排列方式. 代码演示: #include <iostr ...

  2. python把list的所有元素生成排列和组合

    2019独角兽企业重金招聘Python工程师标准>>> 生成排列可以用 itertools.product: from itertools import product l = [1 ...

  3. 生成排列(全排列)的两种写法

    问题简述:输出任意各自然数(可不连续)所有不重复的排列,即全排列,要求所产生的任一数字序列中不允许出现重复的数字. 解决方法:1.交换法    2.数组访问法,两种方法都是由dfs回溯完成,也可以使用 ...

  4. C语言编写Johnson-Trotter算法生成排列

    //Johnson-Trotter算法生成排列#include<stdio.h>int list[99];在这里插入代码片 int num[99]; int dir[99];int cha ...

  5. Johnson_Trotter 生成排列算法

    const int N = 10; int f[N],d[N];void init(int n) {for(int i=1; i<=n; i++)f[i]=i,d[i]=-1; }void Pr ...

  6. 用Johnson-Trotter算法生成排列!

    package decreaseAndConquer; /* * 实现用来生成排列的Johnson-Trotter算法 * 输入:一个正整数n * 输出:{1,...,n}的所有排列的列表 */ im ...

  7. 组合数学 ch4 生成排列和组合

    1.生成排列 n个正整数组成的集合{1,2,...,n}有n!个排列 如何生成全排列? 组合数学新算法:交错插入法. 简单来说,一次次生成{1}到{1,2}到{1,2....n}所有的排列,用当前排列 ...

  8. 谁说GPT只擅长生成?清华研究力证:GPT语言理解能力不输BERT

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者|张倩.小舟 来源|机器之心 一直以来,GPT 模型的语言生成能 ...

  9. python 生成排列、组合以及选择

    from <python cookbook> 19.15 任务 需要对一个序列的排列(permutation).组合(combination)或选择(selection)进行迭代操作.即使 ...

  10. 排列组合之生成排列_(:з」∠)_

    1.生成全排列 第一类:按字典序生成 参考: http://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html 1.字典序法 通过一个已知排列, ...

最新文章

  1. orcale 日期转字符串 去掉0_C# 基础知识系列- 13 常见类库介绍(二)日期时间类...
  2. ECShop 模板库项目功能详解
  3. Nginx.代理MySQL
  4. 关于write()和fsync()
  5. 四十、SPSS数据汇总,图表制作,频率分析和描述分析
  6. mysql的联合查询差集_MySQL实现差集(Minus)和交集(Intersect)
  7. 教育部:向高校免费开放2.4万余门在线课程(附22个平台链接)
  8. 超融合硬件损坏导致Oracle RAC异常恢复实录
  9. 使用DOM4J解析XML及采用Schema校验的方法
  10. 一个网站图标引发的血案!绕过同源策略,判断你是否登录了某网站
  11. java中普通变量、静态变量、静态代码块初始化的顺序辨析
  12. 分享活动报名收费的微信小程序制作功能介绍_瑜伽健身房培训报名小程序开发介绍
  13. 【工具】聊聊文件传输工具,网页文件传输工具Snapdrop好用不
  14. 【大数据】HBase集群部署
  15. 推荐一个在线办公协作的
  16. redission实现分布式锁
  17. 解决手机不能设置DeviceOwner权限提示already provisioned问题
  18. 数据可视化之美-动态图绘制【补充】(以Python为工具)
  19. matlab中门函数怎么化,Matlab中函数tf2zp的解析
  20. 加密php代码一担粮,分享8个PHP开发常用代码片段_后端开发

热门文章

  1. WRF4.2安装过程全记录
  2. kaptcha生成自定义图片验证码
  3. JAVA_数字转大写
  4. C/C++ 字符数字-‘0‘ 字符数字+‘0‘ 是什么意思
  5. vc2005 应用程序正常初始化(0XC0150002)失败
  6. python终端会话是指什么_进程组、会话、控制终端的概念及程序
  7. DeleteRow()
  8. 如何以管理员身份运行powerShell
  9. php简述微信支付接口开发流程,php微信支付接口开发程序(流程已通)
  10. Pytorch(三):数据变换 Transforms