Sicily 2011. Nine Digits

本文详细介绍了使用康托压缩和广度优先搜索算法解决排列问题的方法,通过从最小排列开始逐步扩展,高效地找到所有可能的排列,并通过常数时间查找优化了结果输出。

解题思路是宽搜+康托压缩。具体就是从123456789开始向外宽搜,找到所有情况并记录,然后对输入进行常数时间的查找,最后输出结果。另外,由于1到9的全排列有9!个,不加处理直接开数组的话,可以开10^9(10表示1-10这10个数,9表示有9个位)个,但是这样空间就很大。而利用康托压缩,根据全排列中每个数只会出现一次的实际情况,可以将数组大小从10^9压缩为9!个,也即是去除了重复出现某些数字(缺失某些数字)的排列情况,具体实现请参考代码。
另:简言之,康托压缩是通过判断当前排列在全排列中属于第几大排列而实现的。

Run Time: 0.67sec

Run Memory: 2120KB

Code length: 3177Bytes

SubmitTime: 2012-01-12 01:13:13

// Problem#: 2011
// Submission#: 1188530
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <cstdio>
#include <queue>
using namespace std;

int factorial[ 9 ] = { 40320, 5040, 720, 120, 24, 6, 2, 1, 1 };
int tile[ 362880 ] = { };

void rotate1( int from[], int to[] );
void rotate2( int from[], int to[] );
void rotate3( int from[], int to[] );
void rotate4( int from[], int to[] );

void itoa( int n, int a[] ) {
    for ( int i = 8; i >= 0; i-- ) {
        a[ i ] = n % 10;
        n /= 10;
    }
}

int atoi( int a[] ) {
    int n = 0;
    for ( int i = 0; i < 9; i++ )
        n = n * 10 + a[ i ];
    return n;
}

int cantor( int a[] ) {
    int i, j, count, n = 0;
    for ( i = 0; i < 9; i++ ) {
        count = 0;
        for ( j = i + 1; j < 9; j++ ) {
            if ( a[ i ] > a[ j ] )
                count++;
        }
        n += count * factorial[ i ];
    }
    return n;
}


int main()
{
    int i;
    queue<int> q;
    int n, size, step;
    int temp[ 9 ], now[ 9 ];

    step = 0;
    q.push( 123456789 );
    while ( !q.empty() ) {
        size = q.size();
        while ( size-- ) {
            itoa( q.front(), now );

            rotate1( now, temp );
            n = cantor( temp );
            if ( tile[ n ] == 0 ) {
                tile[ n ] = step + 1;
                q.push( atoi( temp ) );
            }

            rotate2( now, temp );
            n = cantor( temp );
            if ( tile[ n ] == 0 ) {
                tile[ n ] = step + 1;
                q.push( atoi( temp ) );
            }

            rotate3( now, temp );
            n = cantor( temp );
            if ( tile[ n ] == 0 ) {
                tile[ n ] = step + 1;
                q.push( atoi( temp ) );
            }

            rotate4( now, temp );
            n = cantor( temp );
            if ( tile[ n ] == 0 ) {
                tile[ n ] = step + 1;
                q.push( atoi( temp ) );
            }

            q.pop();
        }
        step++;
    }
    tile[ 0 ] = 0;
    
    while ( scanf( "%d", &now[ 0 ] ) != EOF ) {
        for ( i = 1; i < 9; i++ )
            scanf( "%d", &now[ i ] );
        printf( "%d\n", tile[ cantor( now ) ] );
    }

    return 0;

}

void rotate1( int from[], int to[] ) {
    to[ 0 ] = from[ 1 ];
    to[ 1 ] = from[ 4 ];
    to[ 2 ] = from[ 2 ];
    to[ 3 ] = from[ 0 ];
    to[ 4 ] = from[ 3 ];
    to[ 5 ] = from[ 5 ];
    to[ 6 ] = from[ 6 ];
    to[ 7 ] = from[ 7 ];
    to[ 8 ] = from[ 8 ];
}

void rotate2( int from[], int to[] ) {
    to[ 0 ] = from[ 0 ];
    to[ 1 ] = from[ 2 ];
    to[ 2 ] = from[ 5 ];
    to[ 3 ] = from[ 3 ];
    to[ 4 ] = from[ 1 ];
    to[ 5 ] = from[ 4 ];
    to[ 6 ] = from[ 6 ];
    to[ 7 ] = from[ 7 ];
    to[ 8 ] = from[ 8 ];
}

void rotate3( int from[], int to[] ) {
    to[ 0 ] = from[ 0 ];
    to[ 1 ] = from[ 1 ];
    to[ 2 ] = from[ 2 ];
    to[ 3 ] = from[ 4 ];
    to[ 4 ] = from[ 7 ];
    to[ 5 ] = from[ 5 ];
    to[ 6 ] = from[ 3 ];
    to[ 7 ] = from[ 6 ];
    to[ 8 ] = from[ 8 ];
}

void rotate4( int from[], int to[] ) {
    to[ 0 ] = from[ 0 ];
    to[ 1 ] = from[ 1 ];
    to[ 2 ] = from[ 2 ];
    to[ 3 ] = from[ 3 ];
    to[ 4 ] = from[ 5 ];
    to[ 5 ] = from[ 8 ];
    to[ 6 ] = from[ 6 ];
    to[ 7 ] = from[ 4 ];
    to[ 8 ] = from[ 7 ];
}                                 


 

通过短时倒谱(Cepstrogram)计算进行时-倒频分析研究(Matlab代码实现)内容概要:本文主要介绍了一项关于短时倒谱(Cepstrogram)计算在时-倒频分析中的研究,并提供了相应的Matlab代码实现。通过短时倒谱分析方法,能够有效提取信号在时间与倒频率域的特征,适用于语音、机械振动、生物医学等领域的信号处理与故障诊断。文中阐述了倒谱分析的基本原理、短时倒谱的计算流程及其在实际工程中的应用价值,展示了如何利用Matlab进行时-倒频图的可视化与分析,帮助研究人员深入理解非平稳信号的周期性成分与谐波结构。; 适合人群:具备一定信号处理基础,熟悉Matlab编程,从事电子信息、机械工程、生物医学或通信等相关领域科研工作的研究生、工程师及科研人员。; 使用场景及目标:①掌握倒谱分析与短时倒谱的基本理论及其与傅里叶变换的关系;②学习如何用Matlab实现Cepstrogram并应用于实际信号的周期性特征提取与故障诊断;③为语音识别、机械设备状态监测、振动信号分析等研究提供技术支持与方法参考; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,先理解倒谱的基本概念再逐步实现短时倒谱分析,注意参数设置如窗长、重叠率等对结果的影响,同时可将该方法与其他时频分析方法(如STFT、小波变换)进行对比,以提升对信号特征的理解能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值