NOIP2004 火星人(全排列)

2023-10-27

题目来源:http://acm.wust.edu.cn/problem.php?id=1074&soj=0

题目描述:火星人共有N个手指,每个手指分别代表着1-N共N个数,可以通过改变这个这N个手指的顺序来改变值的大小。但是人类想要和火星人交流,就必须通过科学家,科学家先将火星人讲的话(手指表示的数)翻译成我们能理解的语言(如火星人共3个手指,则123 132 213 231 312 321分别代表1 2 3 4 5 6),然后告诉你一个数,你把这个数和火星人讲的话加起来回给科学家,科学家再翻译成火星人的语言。本题给出火星人的手指数N、要加的数M和手指的顺序num[N],要求输出火星人收到的回话。


刚开始看到这个题目,还是有点懵逼的,但是知道它是一个全排列问题,所以赶紧的去了解了一下全排列,顺利地解决了这个问题。


本题就是要求求出num[N]经过M次排列后的结果。


对于一系列的数,比如int num[5] = {1,2,3,4,5}这个数组,要想对它进行全排列,要经过以下几个步骤:


1.判断该数组能不能进行全排列

对于一个数组来说,如果他为num[5] = {5,4,3,2,1},那么也就没有必要再去全排列了,因为他已经是最大的数字了,没有后继。所以,想要判断一系列数能不能进行全排列,判断他有没有后继(即这个数是否存在非递减的两个数),如果有(存在),那就可以进行排列。

判断是否能进行全排列的代码:

bool hasNext()
{
    for( int i = N; i > 0; i--)
        if( num[i] > num[i-1])
            return true;
    return false;
}

2.如何进行全排列(当时想这个想了挺久的==)

在确定这一系列的数有后继之后,那如何去找到它的后继呢?要明确,一个数的后继要满足两个条件:比这个数大、在比这个数大的数里面最小。

首先,我们从右往左遍历这个数组,找出一个数num[i],满足num[i]>num[i-1],然后用top将这个i记录下来(即top为极大值点),并且确定了一个要交换的数num[top-1];

接着,我们要确定第二个要交换的数, 而第二个要交换的数为num[top]-num[N]中最小的数并且这个数要大于第一个被交换的数num[top-1];

然后,交换两个数;

最后,如果交换之后,num[top]及其后面的数如果还是单调递减的,那就将其位置对调,得到最小的。

找出极大值得top并记录

for( int i = N-1; i >0; i--)
    {
        if( num[i] > num[i-1])
        {
            top = i;
            break;
        }
    }


确定第二个要交换的数

int mm = top;//mm为要交换数的下标
    //如果top后面还有比top前面的数(也就是num[top-1)小的话,就先交换那个小的数
    for( int i = top; i < N; i++)
    {
        if( num[i] > num[top-1] && num[i] < num[top])
            mm = i;
    }

交换两个数

void _swap( int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
_swap(&num[mm],&num[top-1]);

得到最小

for(int i=0;i<=(top+N-1)/2-top;i++)
        _swap(&num[i+top],&num[N-1-i]);


大概的思路就是这个样子了==

可能讲的还不是太清楚,其实对于全排列问题,用递归、c++的库函数都可以完成的。

源码:

#include<cstdio>

using namespace std;
const int maxn = 10000+5;
int num[maxn];
int N,M;

//个人觉得这个不写也没问题,但是为了安全,还是写着吧
int hasNext()
{
    for( int i = N-1; i > 0; i--)
        if( num[i] > num[i-1])
            return true;
    return false;
}

void _swap( int *a, int *b)
{
    int m = *a;
    *a = *b;
    *b = m;
}

void next()
{
    int top;
    //从又开始遍历数组,找出右边第一个极大值,用top保存(此时也找到了第一个要交换的数num[top-1])
    for( int i = N-1; i > 0; i--)
       if( num[i] > num[i-1])
       {
           top = i;
           break;
       }

    //找出第二个要交换的数
    int mm = top;
    for( int i = top; i < N; i++)
    {
        if( num[i] > num[top-1] && num[i] < num[top])
            mm = i;
    }

    _swap( &num[top-1], &num[mm]);

    for( int i = 0; i <= (top+N-1)/2-top; i++)
        _swap( &num[i+top], &num[N-1-i]);

}

int main()
{
    while( scanf("%d%d",&N,&M) == 2)
    {

        for( int i = 0; i < N; i++)
            scanf("%d",&num[i]);

        for( int i = 0; i < M; i++)
        {
            if( hasNext())
                next();
        }

        printf("%d",num[0]);
        for( int i = 1; i < N; i++)
            printf(" %d",num[i]);
        printf("\n");

    }

    return 0;
}

//用vector容器不用数组更容易实现呢==


用c++中的库函数

#include<cstdio>
#include<algorithm>

using namespace std;
const int maxn = 10000+5;
int num[maxn];

int main()
{
    int n,m;
    while( scanf("%d%d",&n,&m) == 2)
    {
        for( int i = 0; i < n; i++)
            scanf("%d",&num[i]);

        for( int i = 0; i < m; i++)
            next_permutation(num,num+n);

        for( int i = 0; i < n; i++)
            printf(i==n-1?"%d\n":"%d ",num[i]);

    }

    return 0;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NOIP2004 火星人(全排列) 的相关文章

  • 【刷题】华为笔试面试机考 [HJ29] - 字符串加解密

    题目地址 点击跳转 题目描述 1 对输入的字符串进行加解密 并输出 2 加密方法为 当内容是英文字母时则用该英文字母的后一个字母替换 同时字母变换大小写 如字母a时则替换为B 字母Z时则替换为a 当内容是数字时则把该数字加1 如0替换1 1
  • Kattis Doors

    Problem open kattis com problems doors vjudge net contest 183886 problem B Reference 点到线段的最短距离算法 Meaning 有两个球 Alex 和 Bob
  • hdu 5818 Joint Stacks 2016 Multi-University 7

    Problem acm hdu edu cn showproblem php pid 5818 官方题解 bestcoder hdu edu cn blog 2016 multi university training contest 7
  • hdu 2024C语言合法标识符

    链接http acm hdu edu cn showproblem php pid 2024 思路 根据定义写 1 所有标识符必须由一个字母 a z或A Z 或下划线 开头 2 标识符的其它部分可以用字母 下划线或数字 0 9 组成 3 大
  • POJ-2676 Sudoku(简单数独-dfs深搜)

    Sudoku Time Limit 2000MS Memory Limit 65536K 题目链接http poj org problem id 2676 Description Sudoku is a very simple task A
  • 蓝桥杯 砝码称重 递归 解题报告

    5个砝码 用天平称重时 我们希望用尽可能少的砝码组合称出尽可能多的重量 如果只有5个砝码 重量分别是1 3 9 27 81 则它们可以组合称出1到121之间任意整数重量 砝码允许放在左右两个盘中 本题目要求编程实现 对用户给定的重量 给出砝
  • stl_set

    begin 返回指向第一个元素的 迭代器 clear 清除所有元素 size 集合中元素的数目 count 返回某个值元素的个数 empty 如果集合为空 返回true 真 end 返回指向最后一个元素之后的迭代器 不是最后一个元素器 in
  • hdu 4712 Hamming Distance

    Problem acm hdu edu cn showproblem php pid 4712 Reference 多向 bfs 思路 CSDN markdown 用 LaTeX Meaning 定义两个整数数 a 和 b 的汉明距离为 a
  • hdu 1255 覆盖的面积

    Problem acm hdu edu cn showproblem php pid 1255 Reference hdu 1255 覆盖的面积 矩形面积并 矩形面积交 矩形周长并 线段树 扫描线总结 Meaning 给出 n 个矩形 求它
  • [django项目] 利用elasticsearch实现搜索功能

    新闻搜索 I 搜索功能分析 本节我们来完成新闻搜索功能 首先让我们来思考一下 要做一个通过关键词搜索文章的功能 需要搜索哪些字段 以及使用什么技术方案呢 既然我们是准备做新闻博客网站 那我们就可以拿同类型网站的做一下对比 例如CSDN 简书
  • 简单的动态规划——装箱问题

    装箱问题 告诉你箱子的容积为多少 告诉你有N件物品和每一件物品的体积 问如何选择物品才能令箱子的剩余容积最小 搜索递归 include
  • hdu 6208 The Dominator of Strings

    Problem acm hdu edu cn showproblem php pid 6208 Meaning 有 n 个字符串 问是否能找到其中一串 使得其它串都是它的子串 Analysis 如果存在这个串 那它一定是 n 个中的最长串
  • ES学习——介绍

    前言 在了解Elasticsearch之前 我们应该先了解下 什么是搜索引擎 目前有哪些主流的搜索引擎 搜索引擎搜索的质量应该如何评价 简介 什么是ES es全称为Elasticsearch 是一个高度可扩展且开源的全文检索和分析引擎 它可
  • gym 101505 CTU Open Contest 2016 G Orchard Division

    Problem codeforces com gym 101505 attachments vjudge net contest 187874 problem G Meaning 一个 m m 的网格 长 宽下标 0 m 1 里有 n 个点
  • hduoj 2002

    计算球体积 Problem Description 根据输入的半径值 计算球的体积 Input 输入数据有多组 每组占一行 每行包括一个实数 表示球的半径 Output 输出对应的球的体积 对于每组输入数据 输出一行 计算结果保留三位小数
  • dfs全排列总结

    17 Letter Combinations of a Phone Number Medium 12161744Add to ListShare Given a string containing digits from 2 9 inclu
  • hdu 3966 Aragorn's Story

    Problem acm hdu edu cn showproblem php pid 3966 Reference 树链剖分 树链剖分原理 树链剖分详解及模板 HDU3966 树链剖分 Meaning 一棵 n 个点的树 每给结点有个值 三
  • GYM-102920-L. Two Buildings(决策单调性+分治)

    题目链接 题目大意 求一段序列的 h i h j j i 的最大值 step1 转化一下题意 h i h j j i h j h i j i 令a i h i b i h i 然后全部转化为两种坐标 i a i i b i 这样题目就转化成
  • Ugly Numbers

    题目描述 Ugly numbers are numbers whose only prime factors are 2 3 or 5 The sequence 1 2 3 4 5 6 8 9 10 12 shows the first 1
  • Android WiFi开发教程(二)——WiFi的搜索和连接

    在上一篇中我们介绍了WiFi热点的创建和关闭 如果你还没阅读过 建议先阅读上一篇文章Android WiFi开发教程 一 WiFi热点的创建与关闭 本章节主要继续介绍WiFi的搜索和连接 WiFi的搜索 搜索wifi热点 private v

随机推荐

  • 时间序列 R 08 指数平滑 Exponential smoothing

    1 1 简单指数平滑 simple exponential smoothing SES SES适用于不计趋势与季节性的时间序列 我们在可以使用平均值模型和naive模型来做粗略的预测 点击查看 他们懂预测方法分别是 使用最后一个值 naiv
  • STM32F042 CAN使用例子

    代码如下 include mycan h CAN初始化 tsjw 重新同步跳跃时间单元 范围 1 3 CAN SJW 1tq CAN SJW 2tq CAN SJW 3tq CAN SJW 4tq tbs2 时间段2的时间单元 范围 1 8
  • tensorfllow-gpu遇到gpu资源不够的情况

    本人windows10测试tensorflow gpu的资源使用情况 开启两个tensorflow gpu进程 两个进程的代码一致 第一个进程创建随机变量后gpu使用情况如下 第二个进程创建随机变量时gpu使用情况如下 可以看到已经快使用完
  • Linux配置和使用Git

    本文已收录至 Linux知识与编程 专栏 作者 ARMCSKGT 演示环境 CentOS 7 目录 前言 正文 注册Giett构建仓库 注册giett 构建仓库 Linux配置Git 下载Git 配置Git用户名 配置Git账户邮箱 验证是
  • Qt(c++)调用海康威视监控摄像头

    文章目录 一 海康威视监控摄像头开发SDK介绍 二 海康SDK模块说明 三 Qt项目中海康威视SDK配置 四 实时预览摄像头图像程序 一 海康威视监控摄像头开发SDK介绍 设备网络SDK是基于设备私有网络通信协议开发的 为嵌入式网络硬盘录像
  • 探究软件测试人员的进阶之路

    一谈到进阶 大部分文章 包括前面一些文章也会写到职级如何从初级 中级 高级 一直进阶到专家级 然后写上每个级别所需要的知识技能 然而 我们掌握了这些所谓初 中 高的知识和技能 真的就能成为测试专家了吗 对于这个问题 大部分人应该都带着疑惑或
  • qt导入html css样式表,第45篇 进阶(五)Qt样式表

    第45篇 进阶 五 Qt样式表 导语 一个完善的应用程序不仅应该有实用的功能 还要有一个漂亮的外观 这样才能使应用程序更加友善 更加吸引用户 作为一个跨平台的UI开发框架 Qt提供了强大而灵活的界面外观设计机制 Qt样式表是一个可以自定义部
  • 分数阶导数的意义_导数的意义

    分数阶导数的意义 钙衍生物 CALCULUS DERIVATIVES After derivative theory posts we will start to see some of the applications that make
  • 私人用的红帽linux,红帽宣布为个人开发者提供16个RHEL免费许可 支持在生产环境中使用...

    自从红帽宣布结束CentOS操作系统后就引起很多争议 按红帽计划CentOS 8将是最后的版本并且会在年底停更 这使得很多依赖该操作系统的个人和企业无比愤怒 因为这突如其来的变更将会导致大量生产环境需要更换系统 现在红帽为平息用户愤怒正在扩
  • 双极性SPWM波生成

    本篇文章主要介绍用于逆变电路的双极性SPWM波生成 SPWM波就是脉冲宽度按正弦规律变化和正弦波等效的PWM波形 用于控制逆变电路中开关器件的通断 使其输出的脉冲电压的面积与所希望输出的正弦波在相应区间内的面积相等 经滤波后可以得到正弦波输
  • @Transactional事务中发送MQ消息,事务还未完成但是消息已经发送

    Transactional事务中发送MQ消息 事务还未完成但是消息已经发送 这种情况会导致一些问题 1 事务还未提交 但是消息已经发送 这个时候消息中的一些信息提供给别人调用 但是别人调用并没有在数据库找到该记录 因为事务还未提交 2 事务
  • 多线程面试题

    目录 1 僵尸进程和孤儿进程 1 1 孤儿进程定义 1 2 僵尸进程定义 1 2 怎样来清除僵尸进程 1 kill杀死元凶父进程 一般不用 2 父进程用wait或waitpid去回收资源 方案不好 3 通过信号机制 在处理函数中调用wait
  • 8种方案,保证缓存和数据库的最终一致性

    订阅专栏 前言 我们通常使用缓存机制来提升系统的性能 缓存系统下的读写操作 一般都需要操作数据库与缓存 对于读操作 一般是先查询缓存 查询不到再查询数据库 最后回写进缓存 而对于写操作 究竟是先删除 更新 缓存 再更新数据库 还是先更新数据
  • open build service打包deb,并浅谈一点

    详细打包步骤注意 https zh opensuse org openSUSE Build Service Debian builds 认识 浅谈如何认识open build service的 最近在研究软件打包分发和发布的相关知识 发现了
  • CSS 预处理工具 Less 的介绍及使用 步骤

    文章目录 Less是什么 Less的使用方法 Less 中的注释 Less 中的变量 Less 中的嵌套 Less 中的混合 Mixin Less 中的运算 Less 中的转译 Less 中的作用域 Less 中的导入 Less实用实例 文
  • zipkin接入mysql【windows】

    java jar zipkin jar 这种方式启动数据是保存在内存中的 下面我们配置一下将数据保存到mysql中 创建数据库 CREATE DATABASE zipkin 创建表结构 表结构内容参考以下连接 https github co
  • STM32CubeIDE设置Flash烧录地址和大小(告别Keil魔术棒)

    STM32CubeIDE中设置Flash烧写地址和范围 在由Keil平台转到STM32CubeIDE平台过程中 我们熟悉的点开魔术棒进行相关烧录配置的方式已经不适用了 在STM32CubeIDE平台中我们需要通过修改文件的方式来实现 稍显麻
  • sublime text3 python 代码提示_Sublime Text3+Anaconda插件实现智能提示python IDE

    导读 前言上期给你们介绍装Sublime Text3和Python环境 可以编写简单的python类库sublime text3 python 可是却不能像其它IDE一样智能提醒 这样用这个意义也就不大了 今天就给你们推荐python智能提
  • jeecg boot笔记(一)-使用模糊查询

    1 引入 JInput import JInput from components jeecg JInput vue 2 使用
  • NOIP2004 火星人(全排列)

    题目来源 http acm wust edu cn problem php id 1074 soj 0 题目描述 火星人共有N个手指 每个手指分别代表着1 N共N个数 可以通过改变这个这N个手指的顺序来改变值的大小 但是人类想要和火星人交流