1-6 3ウェイマージに4タップを使用してマージする105の実行がある場合、実行を分散します。

1-6
3方向マージに4タップを使用してマージする105の実行がある場合、(17、32、56)のように実行を不均等に分散すると、均等な分散(35、35、35)よりもパスの数が少なくなります。 。

(2分)

T

F
回答:F

紙テープ4、3ウェイマージ
17 32 56 0
0 15 39 17
15 0 24 2
13 2 22 0
11 0 20 2
9 2 18 0
7 0 16 2
5 2 14 0
3 0 12 2
1 2 10 0
0 1 9 1
1 0 8 0
0 0 7 1
0 1 6 0
0 0 5 1
0 1 4 0
0 0 3 1
0 1 2 0
0 0 1 1
0 1 0 0
19ステップが実行され
、4枚の紙テープ、3回のマージ
35 35 35 0
0 0 0 35
1 1 0 11
0 0 1 10
0 1 0 9
0 0 1 8
0 1 0 7
0 0 1 6
0 1 0 5
0 0 1 4
0 1 0 3
0 0 1 2
0 1 0 1
0 0 1 013
ステップが実行されました

コードが間違っている可能性がありますが、この質問には正しく機能します



void printArr(int *arr, int len) {
    
    
    for (int i = 0; i < len; i++) {
    
    
        printf("%4d ", arr[i]);
    }
    printf("\n");
}

class MathUtil {
    
    


public:

    
    static int onlyOneNot0(const int *arr, int len) {
    
    
        int cnt = 0;
        for (int i = 0; i < len; i++) {
    
    
            if (arr[i] != 0)cnt++;
        }
        return cnt == 1;
    }
    //    35 : split 12 12 11 最平均分的整数,
    static std::vector<int> splitKNum(int num, int k) {
    
    
        using namespace std;
        vector<int> v;
        int ceilNum = ceil((double) num / k);
        int floorNum = floor((double) num / k);
//        printf("ceilNum: %d, floorNum: %d\n", ceilNum, floorNum);
//        https://www.cnblogs.com/mycapple/archive/2012/08/07/2626431.html
        for (int i = 0; i < k - 1; i++) {
    
    
            v.emplace_back(ceilNum);
        }
        v.emplace_back(floorNum);
//        cout << ListUtil::toString(v) << "\n";
        return v;
    }


};


//Polyphase Merge Sort
//纸带比way多1 
class KWay {
    
    
    int secondMaxIndex;
    int maxIndex;
    int zeroIndex;
    int *arr;
    int len;
public:
   
 KWay(int *arr, int len) : arr(arr), len(len) {
    
    }
 KWay(int *arr, int len, bool simple) : arr(arr), len(len), simple(simple) {
    
    }
 int onlyOneNot0() {
    
    
        int cnt = 0;
        for (int i = 0; i < len; i++) {
    
    
            if (arr[i] != 0) {
    
    
                cnt++;
                notZeroIndex = i;
            }
        }
//        printf("notZeroIndex:%d\n", notZeroIndex);
        return cnt == 1;
    }

  void putNums(std::vector<int> v) {
    
    
        int vIndex = 0;
        for (int i = 0; i < len; i++) {
    
    
            if (arr[i] == 0) {
    
    
                arr[i] = v[vIndex++];
            } else {
    
    
                arr[i] = 0;
            }
        }
    }

    void run() {
    
    
        printf("纸带%d条,%d路%s归并\n", len, len - 1,simple?"简单":"");
        std::string str;
        int cnt = 0;
        while (true) {
    
    
            if (cnt > 100) {
    
    
                printf("循环超出100,肯定哪里有错误了,调试下吧\n");
                break;
            }
//            printVector(v);
            printArr(arr, len);
//            str += ListUtil::toString(arr, len) + "\n";
//            MathUtil::onlyOneNot0(arr, len)
            if (onlyOneNot0()) {
    
    
//                如果是简单归并的话 这里要分开了 如果有3个0 就把数字分成3份
                if (!simple)
                    break;
//                len-1 是k
                if (arr[notZeroIndex] == 1)break;
//                0 0 0 1 这样子的 就是可以退出了 已经做好了
                std::vector<int> numsAve = MathUtil::splitKNum(arr[notZeroIndex], len - 1);
//                std::cout << ListUtil::toString(numsAve) << "\n";
                putNums(numsAve);
            }
//            MaxAndSecMaxNumVector maxAndSecMaxNumVector=MaxAndSecMaxNumVector::GetSecondMaxNumberIndex(v);
//            maxIndex,secMaxIndex=
//            auto maxIndexAndSecMaxIndex = GetSecondMaxNumberIndexRetStruct(arr, len);
        第二大的数字变成0
//            第一大的变成 - 去
//            第二大的数字
//            GetSecondMaxNumberIndex();
            int minIndex = getMinNot0();
            if (minIndex == -1) {
    
    
//                全是0
                break;
            }
//            0 放最小数字
//其他不是0的位置,- 最小数字
//4 tape 出现两个0的话,那个0 就不管了
            int minNum = arr[minIndex];
            for (int i = 0; i < len; i++) {
    
    
                if (arr[i] == 0)continue;
//                if(arr[i]==arr[minIndex])continue;
                arr[i] -= minNum;
//    if(arr[i]==arr[minIndex])
            }
            arr[zeroIndex] = minNum;

//            arr[maxIndex] -= arr[secondMaxIndex];
//            arr[zeroIndex] = arr[secondMaxIndex];
//            arr[secondMaxIndex] = 0;
            cnt++;

        }
        printf("进行了%d步\n", cnt);
//        https://www.cnblogs.com/li-ning/p/9490053.html
//        std::ofstream fout;
//        fout.open("kWay.csv");



//        std::ofstream fout("kWay.csv");
//        fout << str;
//        std::cout << str << "\n";
//        fout << std::flush;
//        fout.close();
    }

private:
//    找出一个数组最小的数字的下标 除了0的,顺便把0的下标也找了
    int getMinNot0() {
    
    
        int minIndex = 0;
//        if (arr[0] == 0)minIndex = 1;
        while (arr[minIndex]==0)minIndex++;
        if(minIndex>=len){
    
    
            printf("全是0,有问题\n");
            return -1;
        }
        for (int i = 0; i < len; i++) {
    
    
            if (arr[i] == 0) {
    
    
                zeroIndex = i;
                continue;
            }
//            todo
            if (arr[minIndex] > arr[i]) {
    
    
                minIndex = i;
            }
        }
//        printf("min num:%d\n",arr[minIndex]);
        return minIndex;
    }

   

};

コードを実行する

   int arr1[4]{
    
    17, 32, 56,0};
    KWay(arr1,4).run();

    int arr2[4]{
    
    35, 35, 35,0};
    KWay(arr2,4, true).run();

おすすめ

転載: blog.csdn.net/jonathan_joestar/article/details/112992830