[PAT基本レベル] 1005続行(3N + 1)の推測

トピック分析

この質問は、少なくとも私は期待していなかった、任意のより良い対処戦略を考えることは容易ではない、一見複雑です。だから、何の方法、ブルートフォースハードドライのシンプルなアイデアはありません。

目標は少し分析を知ることができ、これらの「キー番号」を、識別することで、これは実際にはAまで、それらのKharaziは、操作の数がKharazi推測によって行わルールと呼ばれる他のシーケンス番号(ここに表示されます削除を指しの生成された数列)。

あなたは、このようなアプローチを思い付くことができるように:
最初の番号から始まる、そのKharaziシーケンスを見つけ、その後、トラバースの現在の番号以外のすべての要素の全体の配列は、すべての数字がKharazi列に表示されます見つけます、削除(また、検索背中の大きさを「減らします」)。この後、次の番号に移動し、アレイを介して完全なサイクルまで、前の作業を繰り返します。

あなたは、いくつかの廃棄物を持っているようだリストで、明らかにこれは非常に複雑であり、その後、私は、アレイの言葉が頻繁にシフトを必要とされるであろう使用し、配列のように頻繁に「削除」の要素を見ることができます。代替的には、配列の要素を特徴付けるために追加BOOLアレイ対応を作成することであるので、それらはブール値、対応する番号がfalseに変更され、削除された場合にも有効です。

不明の長さは、Kharaziシーケンスを計算し、配列があまりにも多くのオープンスペースを無駄にしたくない場合は、動的な拡張手段を用いてもよいです。

最後に、すべての非重要な要素のうち「削除」トラバース、タイトルもここ順番に、そうも保全の配列を持つ他、生き残ったそれらの重要な要素を識別するために、配列を反復処理する必要があり、降順に出力するように私たちを必要とし便利な、ので、あなたは再び並べ替えた後、出力をすることができますトピックはありません100個の以上の要素を私たちに語っていますので、サイズ100の直接オープンint配列を保存します。

最適化戦略
は、対象は、要素のサイズが100を超えていない私たちに教えて被験者の状態についての詳細注記を見つけることができる、Kharaziシーケンス毎時間前に我々は、配列のサイズを減らすことになる、100個の以上の要素の計算を保存トラバースを削減していません時間の比較。

ドライダウンすることで、このトピックの全体的なアイデアは、まだ多少面倒、そして最終的に単純挿入ソートで以下のコードを書くためにソート。しかし、前回の比較複雑さと、削除の要素、残りの時間のいくつかの要素がほとんど無視できるという順序に比べて、とても良いパフォーマンスをソートアルゴリズムは、ライン上の簡単な権利を書いていません。

ソース

#include <stdio.h>

const int DEFAULT_SIZE=30;   //设置储存卡拉兹序列数组默认大小为30,满后再进行扩容
void expand(int *&arr,int len);  //对数组扩容
int* findPath(int num,int &len);  //计算卡拉兹猜想过程数
void insertSort(int *arr,int len);   //插入排序

int main()
{
    int caseNumber;
    scanf("%d",&caseNumber);
    getchar();
    int *value=new int[caseNumber];  //储存元素值
    bool *isValid=new bool[caseNumber];  //判断元素是否还有效
    for(int i=0;i<caseNumber;++i){  //读取数据
        scanf("%d",&value[i]);
        isValid[i]=true;  //初始化为true
    }
  
    for(int i=0;i<caseNumber;++i){
        if(!isValid[i]) continue;
        int len=0;
        int* path=findPath(value[i],len);  //计算当前有效元素的卡拉兹路径元素
        for(int j=0;j<caseNumber;++j){  //对除当前元素外所有元素进行遍历,删除被覆盖元素
            if(!isValid[j]||j==i) continue;
            for(int k=0;k<len;++k){
                if(path[k]==value[j]){  //发现路径上的元素,删除
                    isValid[j]=false; 
                    break;
                }
            }
        }
       delete []path;  //释放当前路径数组的空间
    }
    int keys[100];  //剩余数个数不超过100
    int count=0;
    for(int i=0;i<caseNumber;++i){
        if(!isValid[i]) continue;
        keys[count++]=value[i];  //记录剩下的关键数
    }
    insertSort(keys,count);
    for(int i=0;i<count-1;++i)
        printf("%d ",keys[i]);
    printf("%d",keys[count-1]);
    delete []value;
    delete []isValid;
    return 0;
}

void expand(int *&arr,int len)
{
    int *old=arr;
    arr=new int[len*2];  //扩容为原来两倍
    for(int i=0;i<len;++i)
        arr[i]=old[i];
    delete []old;   //释放原空间
}
int* findPath(int num,int &len)
{
    len=1;
    int curSize=1;
    int capacity=DEFAULT_SIZE;
    int * path=new int [capacity];
    path[0]=num;  
    while(num!=1){
        len++;
        if(num%2==0)  num>>=1;
        else num=(3*num+1)>>1;
        if(num<101) path[curSize++]=num;  //仅当所得数值小于101时放入数组
        if(curSize==capacity){  //若数组满,扩容
            capacity<<=1;
            expand(path,curSize);
        }
    }
    return path;
}
void insertSort(int *arr,int len)
{
    for(int i=1;i<len;++i){
        int curOrder=i;
        int pre=i-1;
        while(arr[curOrder]>arr[pre]){
            int tmp=arr[curOrder];
            arr[curOrder--]=arr[pre];
            arr[pre--]=tmp;
            if(curOrder==0) break;
        }
    }
}
发布了11 篇原创文章 · 获赞 1 · 访问量 74

おすすめ

転載: blog.csdn.net/weixin_44452361/article/details/104602637