অতিরিক্ত লোডযুক্ত বিমান থেকে চর্বিযুক্ত লোকদের ছুঁড়ে ফেলা হচ্ছে।


200

ধরা যাক আপনি একটি বিমান পেয়েছেন, এবং এটিতে জ্বালানি কম। বিমানটি যদি 3000 পাউন্ড যাত্রীর ওজন না ফেলে তবে এটি পরবর্তী বিমানবন্দরে পৌঁছাতে সক্ষম হবে না। সর্বোচ্চ সংখ্যক জীবন বাঁচাতে আমরা সবচেয়ে ভারী মানুষকে প্রথমে বিমান থেকে ফেলে দিতে চাই।

এবং হ্যাঁ, বিমানটিতে কয়েক মিলিয়ন লোক রয়েছে এবং আমরা পুরো তালিকাটি বাছাই না করেই সবচেয়ে ভারী যাত্রী খুঁজে পেতে একটি অনুকূল অ্যালগরিদম চাই।

এটি সি ++ এ কোড করার চেষ্টা করছি এমন কোনওর জন্য একটি প্রক্সি সমস্যা। আমি ওজন দ্বারা যাত্রীবাহী ম্যানিফেস্টে "আংশিক_সোর্ট" করতে চাই, তবে আমি জানি না যে আমার কতগুলি উপাদান প্রয়োজন to আমি আমার নিজের "আংশিক_সোর্ট" অ্যালগরিদম ("আংশিক_সোর্ট_ক্যাকুমুলেট_উন্টিল") প্রয়োগ করতে পারি, তবে আমি ভাবছি যে স্ট্যান্ডার্ড এসটিএল ব্যবহার করে এটি করার সহজ উপায় আছে কি না।


5
যদি মানুষের সাথে সাদৃশ্য থাকে তবে আপনি X এর চেয়ে বেশি ওজনের লোকদের ফেলে দিয়ে শুরু করতে পারেন, উদাহরণস্বরূপ, 120 কেজি, যেহেতু এগুলি খুব চর্বিযুক্ত লোকদের মধ্যে হতে পারে।
রেডএক্স

132
সমস্ত যাত্রী কি অ্যালগরিদমের কোনও পদক্ষেপে সহযোগিতা করবে?
লাইয়ার কোগান

34
এই জাতীয় বিষয় কেন আমি আইটি পছন্দ করি।
মার্কাস

14
আমি জিজ্ঞাসা করতে পারি যে এটি কোন বিমান সংস্থাটির জন্য? আমি নিশ্চিত করতে চাই যে আমি কেবল তাদের সাথে ছুটির মরসুমের আগেই উড়ালাম - আমার নিজের উপর নিজেকে জড়িয়ে দেওয়ার পরে নয়।
jp2code

24
যথাযথ সরঞ্জামগুলি (বিল্ট-ইন স্কেলগুলির সাথে ইজেক্টর আসনের মতো) সহ যাত্রীদের সহযোগিতা প্রয়োজন নেই।
জিম ফ্রেড

উত্তর:


102

একটি উপায় হ'ল একটি মিনিট গাদা ( std::priority_queueসি ++ এ) ব্যবহার করা। আপনার MinHeapক্লাস আছে তা ধরে নিয়ে আপনি এটি কিভাবে করবেন তা এখানে's (হ্যাঁ, আমার উদাহরণটি সি # তে রয়েছে I আমি আপনাকে ধারণাটি পেয়েছি বলে মনে করি))

int targetTotal = 3000;
int totalWeight = 0;
// this creates an empty heap!
var myHeap = new MinHeap<Passenger>(/* need comparer here to order by weight */);
foreach (var pass in passengers)
{
    if (totalWeight < targetTotal)
    {
        // unconditionally add this passenger
        myHeap.Add(pass);
        totalWeight += pass.Weight;
    }
    else if (pass.Weight > myHeap.Peek().Weight)
    {
        // If this passenger is heavier than the lightest
        // passenger already on the heap,
        // then remove the lightest passenger and add this one
        var oldPass = myHeap.RemoveFirst();
        totalWeight -= oldPass.Weight;
        myHeap.Add(pass);
        totalWeight += pass.Weight;
    }
}

// At this point, the heaviest people are on the heap,
// but there might be too many of them.
// Remove the lighter people until we have the minimum necessary
while ((totalWeight - myHeap.Peek().Weight) > targetTotal)
{
    var oldPass = myHeap.RemoveFirst();
    totalWeight -= oldPass.Weight; 
}
// The heap now contains the passengers who will be thrown overboard.

মানক রেফারেন্স অনুসারে, চলমান সময়টি আনুপাতিক হওয়া উচিত n log k, যেখানে nযাত্রীর সংখ্যা এবংk সংখ্যা এবং স্তূপে আইটেমের সর্বাধিক সংখ্যা। যদি আমরা ধরে নিই যে যাত্রীদের ওজন সাধারণত 100 পাউন্ড বা তারও বেশি হয়ে থাকে, তবে গাদাটি যে কোনও সময় 30 টিরও বেশি আইটেম ধারণ করবে এমন সম্ভাবনা কম।

সবচেয়ে খারাপ অবস্থাটি যদি যাত্রীদের সর্বনিম্ন ওজন থেকে সর্বোচ্চ পর্যন্ত অর্ডার করে দেওয়া হয়। এর জন্য প্রতিটি যাত্রী গাদাতে যুক্ত হওয়া এবং প্রতিটি যাত্রী গাদা থেকে সরানো দরকার। তবুও, এক মিলিয়ন যাত্রী এবং ধরে নিচ্ছেন যে সবচেয়ে হালকা ওজনের 100 পাউন্ড ওজনেরn log k যুক্তিসঙ্গতভাবে অল্প সংখ্যক হয়ে যায়।

যদি আপনি এলোমেলোভাবে যাত্রীদের ওজন পান, পারফরম্যান্স আরও ভাল। আমি একটি সুপারিশ ইঞ্জিনের জন্য বেশ কিছু এরকম ব্যবহার করি (আমি কয়েক মিলিয়ন এর তালিকা থেকে শীর্ষ 200 আইটেম নির্বাচন করি)। আমি সাধারণত 50,000 বা 70,000 আইটেমগুলি দিয়ে শেষ করি actually

আমি সন্দেহ করি যে আপনি বেশ কিছু অনুরূপ দেখতে পাচ্ছেন: আপনার প্রার্থীদের বেশিরভাগ প্রত্যাখাত হবেন কারণ তারা ইতিমধ্যে গাদা থাকা হালকা ব্যক্তির চেয়ে হালকা। এবং Peekএকটি O(1)অপারেশন।

গাদা কর্মক্ষমতা সম্পর্কে একটি আরও তথ্যের জন্য নির্বাচন করে দ্রুত নির্বাচন করুন, দেখুন তত্ত্ব অনুশীলন পূরণ করে যখন । সংক্ষিপ্ত সংস্করণ: আপনি যদি সামগ্রীর আইটেমের সংখ্যার 1% এরও কম বেছে নিচ্ছেন, তবে দ্রুত নির্বাচন করার ক্ষেত্রে হিপ নির্বাচনটি পরিষ্কার বিজয়ী। 1% এরও বেশি, তারপরে দ্রুত নির্বাচন বা ইন্ট্রোসलेक्टের মতো কোনও রূপ ব্যবহার করুন ।


1
সোপবক্স দ্রুত উত্তর পোস্ট করেছে।
হাঁসকে

7
আমার পড়ার জন্য, সোপবক্সের উত্তর হ'ল জিম মিশেলের উত্তরের নৈতিক সমতুল্য। সোপবক্স সি ++ তে তার কোড লিখেছিল এবং এইভাবে সে একটি স্টাডি :: সেট ব্যবহার করে, যা একই লগ (এন) মিনহ্যাপের মতো সময় যুক্ত করে।
আইভিমাইক

1
একটি লিনিয়ার সময় সমাধান আছে। আমি এটি যুক্ত করব।
নিল জি

2
মিনিট-হ্যাপের জন্য এখানে একটি এসটিএল ক্লাস রয়েছে:std::priority_queue
বিডনলান

3
@ মুভিংডাক: সম্ভবত আপনি ভুল বুঝে গেছেন। আমার কোড খালি হিপ তৈরি করে, ঠিক যেমন সাবানবক্সের কোড একটি খালি সেট তৈরি করে। প্রধান পার্থক্য, যেমনটি আমি দেখছি, তা হ'ল তার কোডটি অতিরিক্ত ওজনের সেটকে ছাঁটাই করে দেয় কারণ উচ্চ ওজনের আইটেম যুক্ত হয়, তবে খনিটি অতিরিক্ত বাড়িয়ে তোলে এবং শেষে এটি ছাঁটাই করে। এই তালিকাটি ভারী লোকদের খুঁজে বের করার সাথে সাথে তার সেটটি আকারে কমবে pot আমার গাদা ওজনের প্রান্তে পৌঁছানোর পরে একই আকারে থাকে এবং আমি তালিকার শেষ আইটেমটি যাচাই করার পরে এটি ছাঁটাই করি।
জিম মিশেল

119

এটি আপনার প্রক্সি সমস্যার জন্য সহায়তা করবে না, তবে:

১,০০,০০০ যাত্রী 3000 পাউন্ড ওজন ছাড়ার জন্য, প্রতিটি যাত্রীকে অবশ্যই লোকসান (3000/1000000) = ব্যক্তিকে 0.003 পাউন্ড হারাতে হবে। এটি প্রত্যেকের শার্ট, বা জুতা, বা এমনকি নখের ক্লিপিংস দিয়ে প্রত্যেককে বাঁচিয়ে জেটসিসিংয়ের মাধ্যমে অর্জন করা যেতে পারে। বিমানটি আরও জ্বালানি ব্যবহার করায় প্রয়োজনীয় ওজন হ্রাস বাড়ার আগে এটি দক্ষ সংগ্রহ এবং জেটিসন ধরে নেয়।

প্রকৃতপক্ষে, তারা আর বোর্ডে নখর কাটা ক্লিপগুলিকে অনুমতি দেয় না, তাই এটি বাইরে।


14
সমস্যাটি দেখার এবং সত্যিকারের আরও ভাল উপায় খুঁজে পাওয়ার সক্ষমতা ভালোবাসুন।
fncomp

19
তুমি একজন প্রতিভাবান. :)
জনাথন

3
আমি মনে করি জুতা একা এটি কভার করবে
1915 এ হাঁসকে মোইং করা

0.003 পাউন্ড 0.048 ওজ, যা আউন্সের মাত্র 1/20 এর নীচে। সুতরাং যদি প্লেনে ষাট জন লোকের মধ্যে একজন মাত্র তিন আউন্স শ্যাম্পু নিয়মের সুযোগ নিচ্ছেন, আপনি কেবল সেই সমস্ত শ্যাম্পু ফেলে দিয়ে দিনটি বাঁচাতে পারবেন।
রায়ান লুন্ডি

43

নীচে সোজা সমাধানটির একটি বরং সাধারণ বাস্তবায়ন দেওয়া আছে। আমি মনে করি না যে এর থেকে আরও দ্রুততর উপায় 100% সঠিক।

size_t total = 0;
std::set<passenger> dead;
for ( auto p : passengers ) {
    if (dead.empty()) {
       dead.insert(p);
       total += p.weight;
       continue;
    }
    if (total < threshold || p.weight > dead.begin()->weight)
    {
        dead.insert(p);
        total += p.weight;
        while (total > threshold)
        {
            if (total - dead.begin()->weight < threshold)
                break;
            total -= dead.begin()->weight;
            dead.erase(dead.begin());
        }
    }
 }

এটি "মৃত লোক" এর সেটটি পূরণ না করা পর্যন্ত কাজ করে যা এর প্রান্তিকের সাথে মিলিত হয়। দোরগোড়টি পূরণ হয়ে গেলে, আমরা হালকা মৃত ব্যক্তির চেয়ে ভারী যে কোনও খুঁজে পাওয়ার চেষ্টা করে এমন যাত্রীদের তালিকার মধ্য দিয়ে চলতে থাকি। যখন আমরা একটি খুঁজে পেয়েছি, তখন আমরা তাদের তালিকায় যুক্ত করি এবং তারপরে হালকা হালকা লোকদের "সংরক্ষণ" শুরু করি যতক্ষণ না আমরা আর সংরক্ষণ করতে পারি না।

সবচেয়ে খারাপ ক্ষেত্রে, এটি পুরো তালিকার সাজানোর মতোই সম্পাদন করবে। তবে সেরা ক্ষেত্রে ("মৃত তালিকা" প্রথম এক্স লোকের সাথে সঠিকভাবে পূরণ করা হয়েছে) এটি সম্পাদন করবে O(n)


1
আমার মনে হয় আপনি আপডেট করতে আছে totalপাশে continue; অন্য যে, এই উত্তর আমি পোস্ট করতে যাচ্ছি হয়। সুপার দ্রুত সমাধান
মাকিং হাঁস

2
এটি সঠিক উত্তর, এটি দ্রুততম উত্তর, এটি সর্বনিম্ন জটিলতার সাথেও উত্তর।
জ্যান্সার টিউলিপ

ডেড.বেগিন () কে ক্যাচ করে এবং শাখা প্রশাখি কমানোর জন্য কিছুটা জিনিস পুনরায় সাজিয়ে আপনি সম্ভবত এটি থেকে আরও কিছুটা বাইরে বের করতে পারেন, যা আধুনিক প্রসেসরগুলিতে বেশ ধীর গতির
Wug

ডেড.বেগিন () সম্ভবত তাত্ক্ষণিক এবং প্রায় অবশ্যই একটি ডেটা অ্যাক্সেসের প্রতি ঝুঁকবে। তবে হ্যাঁ, কয়েকটা আইএফএসের আশেপাশে ঘুরে বেড়ালে শাখা হ্রাস করে আরও কিছুটা পারফরম্যান্স পাওয়া যায় ... তবে সম্ভবত পঠনযোগ্যতার জন্য দুর্দান্ত ব্যয়।
সোপবক্স

1
এটি যৌক্তিকভাবে মার্জিত এবং সামনের দিকে যাত্রীদের # নাম না জেনেও ওপির সমস্ত প্রয়োজনীয়তাকে সম্বোধন করে। এসটিএল ম্যাপস এবং সেটিংগুলির সাথে কাজ করে গত ৫ মাসের বেশিরভাগ সময় ব্যয় করেও আমি নিশ্চিত যে ব্যবহৃত পুনরাবৃত্তির বিস্তৃত ব্যবহার কর্মক্ষমতা পঙ্গু করে দেবে। কেবল সেটটি পপুলেট করুন এবং তারপরে সবচেয়ে ভারী মানুষের যোগফল 3,000 এর চেয়ে বেশি না হওয়া পর্যন্ত ডান থেকে বামে পুনরাবৃত্তি করুন। 1 মিলিয়ন উপাদানগুলির একটি সেট, এলোমেলো ক্রমে উপস্থাপন করা হয়েছে, i5 || i7 3.4Ghz কোরে ~ 30 মিলিয়ন / সেকেন্ডে লোড হবে কমপক্ষে 100 এক্স হিসাবে ধীরে ধীরে Iteration। KISS এখানে জিতবে।
ব্যবহারকারী 2548100

32

সমস্ত যাত্রী সহযোগিতা করবে বলে ধরে নিচ্ছেন: সমান্তরাল বাছাইয়ের নেটওয়ার্কটি ব্যবহার করুন । (এছাড়াও দেখুন এই )

এখানে একটি সরাসরি প্রদর্শন

আপডেট: বিকল্প ভিডিও (1:00 লাফে)

লোককে তুলনা-বিনিময় করতে বলছি - আপনি এর চেয়ে দ্রুত আর পেতে পারবেন না।


1
এটি এখনও এক ধরণের এবং এটি ও (nlogn) হবে। আপনি অবশ্যই একটি ও (এনলগক) হিসাবে দ্রুত পেতে পারেন যেখানে কে << এন, সমাধান সরবরাহ করা হয়েছে।
আদম

1
@ অ্যাডাম: এটি সমান্তরাল বাছাই। বাছাইয়ে ও (এনলগ এন) SEQUENTIAL পদক্ষেপের একটি নিচু সীমানা রয়েছে। তবে তারা সমান্তরাল হতে পারে, তাই সময় জটিলতা অনেক কম হতে পারে। উদাহরণস্বরূপ দেখুন cs.umd.edu/~gasarch/ramsey/parasort.pdf
কোগান

1
ঠিক আছে, ওপি বলছে "আমি সি ++ তে কোড করার চেষ্টা করছি এমন কিছুর জন্য এটি একটি প্রক্সি সমস্যা" " সুতরাং যাত্রীরা সহযোগিতা করলেও তারা আপনার জন্য গণনা করবে না। এটি একটি ঝরঝরে ধারণা, তবে সেই কাগজের অনুমান যে আপনি nপ্রসেসর পাবেন এটি ধারণ করে না।
আদম

@ লিওরকোগান - লাইভ ডেমো ভিডিওটি ইউটিউবে আর উপলভ্য নয়
অ্যাডেলিন

@ অ্যাডেলিন: আপনাকে ধন্যবাদ, বিকল্প ভিডিও যুক্ত করা হয়েছে
লিওর কোগান

21

@ ব্লাস্টফর্নেসটি সঠিক পথে ছিল। পিভটগুলি ওজনের প্রান্তে যেখানে আপনি কুইকসিলিট ব্যবহার করেন। প্রতিটি পার্টিশন এক সেট লোককে একসেটে বিভক্ত করে এবং প্রতিটি সংখ্যক লোকের জন্য মোট ওজন দেয়। আপনার বালতি সর্বোচ্চ ওজনের লোকের সাথে সম্পর্কিত হওয়া পর্যন্ত আপনি যথাযথ বালতিটি ভাঙ্গতে অব্যাহত রাখেন এবং আপনার সেটে থাকা সর্বনিম্ন বালতিতে 1 জন ব্যক্তি রয়েছে (এটি আর কোনও অংশে বিভক্ত হতে পারে না))

এই অ্যালগরিদম লিনিয়ার টাইম ইমোর্টাইজড তবে চতুর্ভুজ খারাপের ক্ষেত্রে। আমি মনে করি এটি একমাত্র লিনিয়ার সময় অ্যালগরিদম


এখানে একটি পাইথন সমাধান রয়েছে যা এই অ্যালগরিদমকে চিত্রিত করে:

#!/usr/bin/env python
import math
import numpy as np
import random

OVERWEIGHT = 3000.0
in_trouble = [math.floor(x * 10) / 10
              for x in np.random.standard_gamma(16.0, 100) * 8.0]
dead = []
spared = []

dead_weight = 0.0

while in_trouble:
    m = np.median(list(set(random.sample(in_trouble, min(len(in_trouble), 5)))))
    print("Partitioning with pivot:", m)
    lighter_partition = []
    heavier_partition = []
    heavier_partition_weight = 0.0
    in_trouble_is_indivisible = True
    for p in in_trouble:
        if p < m:
            lighter_partition.append(p)
        else:
            heavier_partition.append(p)
            heavier_partition_weight += p
        if p != m:
            in_trouble_is_indivisible = False
    if heavier_partition_weight + dead_weight >= OVERWEIGHT and not in_trouble_is_indivisible:
        spared += lighter_partition
        in_trouble = heavier_partition
    else:
        dead += heavier_partition
        dead_weight += heavier_partition_weight
        in_trouble = lighter_partition

print("weight of dead people: {}; spared people: {}".format(
    dead_weight, sum(spared)))
print("Dead: ", dead)
print("Spared: ", spared)

আউটপুট:

Partitioning with pivot: 121.2
Partitioning with pivot: 158.9
Partitioning with pivot: 168.8
Partitioning with pivot: 161.5
Partitioning with pivot: 159.7
Partitioning with pivot: 158.9
weight of dead people: 3051.7; spared people: 9551.7
Dead:  [179.1, 182.5, 179.2, 171.6, 169.9, 179.9, 168.8, 172.2, 169.9, 179.6, 164.4, 164.8, 161.5, 163.1, 165.7, 160.9, 159.7, 158.9]
Spared:  [82.2, 91.9, 94.7, 116.5, 108.2, 78.9, 83.1, 114.6, 87.7, 103.0, 106.0, 102.3, 104.9, 117.0, 96.7, 109.2, 98.0, 108.4, 99.0, 96.8, 90.7, 79.4, 101.7, 119.3, 87.2, 114.7, 90.0, 84.7, 83.5, 84.7, 111.0, 118.1, 112.1, 92.5, 100.9, 114.1, 114.7, 114.1, 113.7, 99.4, 79.3, 100.1, 82.6, 108.9, 103.5, 89.5, 121.8, 156.1, 121.4, 130.3, 157.4, 138.9, 143.0, 145.1, 125.1, 138.5, 143.8, 146.8, 140.1, 136.9, 123.1, 140.2, 153.6, 138.6, 146.5, 143.6, 130.8, 155.7, 128.9, 143.8, 124.0, 134.0, 145.0, 136.0, 121.2, 133.4, 144.0, 126.3, 127.0, 148.3, 144.9, 128.1]

3
+1 টি। এটি একটি আকর্ষণীয় ধারণা, যদিও আমি নিশ্চিত নই যে এটি বেশ লিনিয়ার। আমি যদি কিছু মিস করছি না, বালতির মোট ওজন গণনা করার জন্য আপনাকে আইটেমগুলি নিয়ে পুনরাবৃত্তি করতে হবে এবং প্রতিবার বিভক্ত হয়ে গেলে আপনাকে উচ্চ বালতি (কমপক্ষে আংশিক) পুনরায় গণনা করতে হবে। এটি এখনও সাধারণ ক্ষেত্রে আমার গাদা-ভিত্তিক পদ্ধতির চেয়ে দ্রুততর হবে তবে আমি মনে করি আপনি জটিলতাকে অবমূল্যায়ন করছেন।
জিম মিশেল

2
@Jim: এটা হিসাবে একই জটিলতা হওয়া উচিত quickselect । আমি জানি উইকিপিডিয়ায় বিবরণটি সর্বোত্তম নয়, তবে এটি লিনিয়ার অনুভূত সময়ের কারণ হ'ল প্রতিবার আপনি যখন একটি পার্টিশন করেন, আপনি কেবলমাত্র পার্টিশনের এক পক্ষের সাথে কাজ করেন। অ-কঠোরভাবে, কল্পনা করুন যে প্রতিটি বিভাজন লোককে দুটি ভাগে বিভক্ত করে। তারপরে, প্রথম পদক্ষেপটি O (n), তারপরে O (n / 2) ইত্যাদি গ্রহণ করবে এবং, এন + এন / 2 + এন / 4 + ... = 2 এন।
নিল জি

2
@ জিম: যাইহোক, আপনার অ্যালগরিদমের সবচেয়ে খারাপ ক্ষেত্রে সময় রয়েছে, যখন আমার সেরা গড়ের সময় থাকে। আমি মনে করি যে তারা উভয়ই ভাল সমাধান।
নিল জি

2
@ জিমমিশেল, নীলজি: কোডেপ্যাড.অর্গ.এফএএফএক্স 6 এইচবিটিসি আমি যাচাই করেছি যে সকলেরই একই ফলাফল রয়েছে এবং জিমকে সংশোধন করেছেন। ফুলসোর্ট: 1828 টিক্স। জিমমিশেল: 312 টিক্স। সোপবক্স 109 টিক্স। নীলজি: 641 টিক্স।
46-এ হাঁস মৃগিং করছে

2
@ নীলজি: কোডেপ্যাড.আর্গ / কেএমসিএসভিউডিডি আপনার অ্যালগরিদমের উপায়ে আমার বাস্তবায়ন দ্রুত করার জন্য আমি std :: পার্টিশনটি ব্যবহার করেছি। stdsort: 1812 টিক্স। ফুলহ্যাপ 312 টিক্স। সোপবক্স / জিমমিচল: 109 টিক্স, নীলজি: 250 টিক্স।
হাঁসকে

11

ধরে নিই যে, লোকেদের ওজনের মতো, আপনার সর্বাধিক এবং ন্যূনতম মানগুলি ও (এন) এ বাছাই করার জন্য একটি রেডিক্স সাজ্ট ব্যবহার করার সম্ভাবনা সম্পর্কে আপনার একটি ভাল ধারণা রয়েছে। তারপরে কেবল হালকাতম দিকে তালিকার সবচেয়ে প্রান্ত থেকে কাজ করুন। মোট চলমান সময়: ও (এন)। দুর্ভাগ্যক্রমে, এসটিএলে কোনও র‌্যাডিক্স সাজ্টের প্রয়োগ নেই, তবে এটি লেখা সহজ সোজা।


যদিও আমি সাধারণ রেডিক্স বাছাই করব না, কারণ উত্তর পেতে আপনাকে তালিকাটিকে পুরোপুরি বাছাই করতে হবে না।
শে

1
নির্মল করতে, একটি র্যাডিক্স সাজানোর হয় একটি ভাল ধারণা। একটি কাস্টমাইজড অপ্টিমাইজড লিখতে ভুলবেন না।
হাঁসকে মুছে ফেলছে

1
@ মুভিং: এটি সত্য যে আপনাকে একটি সম্পূর্ণ রেডিক্স বাছাই করতে হবে না, তবে আমি এটি পোস্ট করার সময় কোনও ও (এন) অ্যালগরিদম পোস্ট করা হয়নি এবং এটি দেখতে খুব সহজ ছিল। আমি মনে করি যে নীল জি এর উত্তরটি এখন সে সেরা যে তিনি এটিকে আরও পরিপূর্ণভাবে ব্যাখ্যা করেছেন এবং স্পষ্টভাবে তাঁর নির্বাচনের জন্য মধ্যকটিকে পাইভট হিসাবে ব্যবহার করতে শুরু করেছেন। তবে একটি স্ট্যান্ডার্ড রেডিক্স বাছাই করা কিছুটা সহজ এবং সূক্ষ্ম বাস্তবায়ন বাগের সম্ভাবনা কম, সুতরাং আমি আমার উত্তরটি ছেড়ে যাচ্ছি। একটি কাস্টমাইজড আংশিক র‌্যাডিক্স সাজানোর কাজটি অবশ্যই দ্রুততর হবে, তবে ততটা তাত্পর্যপূর্ণ নয়।
কিথ ইরউইন

6

কেন আপনি "বাছাই করা" এর চেয়ে আলাদা অ্যাওর্ট রুল সহ আংশিক কুইকোর্ট ব্যবহার করবেন না। আপনি এটিকে চালিয়ে যেতে পারেন এবং তারপরে কেবলমাত্র উচ্চতর অর্ধটি ব্যবহার করতে পারেন এবং যতক্ষণ না এই উচ্চতর অর্ধেকের মধ্যে ওজন কমপক্ষে আর ফেলে দিতে হয় না তার ওজন না থাকে যতক্ষণ না আপনি পুনরাবৃত্তির এক ধাপ পিছনে যান এবং তালিকাটি সাজান। এর পরে আপনি সেই সাজানো তালিকার উচ্চ প্রান্ত থেকে লোকদের বাইরে ফেলে দেওয়া শুরু করতে পারেন।


যে নিল জি এর এলগরিদম পিছনে মৌলিক ধারণা আমি এর মনে
20:42-এ হাঁস মৃগিং করছে

এটি কুইকলেক্টের সারাংশ, যা নীল জি ব্যবহার করছেন।
মাইকেল ডোনোহু

6

প্রচুর পরিমাণে সমান্তরাল টুর্নামেন্ট বাছাই করুন: -

অসুস্থতার প্রতিটি পাশের একটি স্ট্যান্ডার্ড তিনটি আসন ধরে নেওয়া: -

  1. উইন্ডো সিটের যাত্রীদের জানালার সিটের ব্যক্তির চেয়ে ভারী হলে মাঝের আসনে যেতে বলুন।

  2. মাঝারি আসনের যাত্রীদের যদি ভারী হয় তবে আইসেল সিটে যাত্রীর সাথে অদলবদল করতে বলুন।

  3. বাম আইল সিটে থাকা যাত্রীকে ডান দিকের আইল সিটের আইডিতে যাত্রীর সাথে অদলবদল করতে বলুন তারা বেশি ভারী।

  4. বুদ্বুদ যাত্রীদের ডান আইল সিটে সাজান। (এন সারিগুলির জন্য n পদক্ষেপ নেয়)। - ডান আইল সিটে থাকা যাত্রীদের বলুন এন -1 বারের সাথে থাকা ব্যক্তির সাথে অদলবদল করতে।

5 আপনি 3000 পাউন্ড না পৌঁছানো পর্যন্ত এগুলি দরজায় ফেলে দিন।

3 টি পদক্ষেপ + এন পদক্ষেপ এবং 30 টি পদক্ষেপ যদি আপনার যদি সত্যিই চর্মসার যাত্রী বোঝা থাকে।

দুটি আইল বিমানের জন্য - নির্দেশাবলী আরও জটিল তবে কর্মক্ষমতা প্রায় একই।


লিয়র কোগানের উত্তর হিসাবে একই, তবে আরও বিশদ।
মুগিং হাঁস

7
একটি "যথেষ্ট ভাল" সমাধান হ'ল "ফ্রি হটডগস" সরবরাহ করা এবং প্রথম পনেরোটি বের করা যা সামনে পৌঁছায়। প্রতিবার অনুকূল সমাধান সরবরাহ করবে না তবে সরল "O" তে চলে।
জেমস অ্যান্ডারসন

সবচেয়ে বেশি 15 টি ফেলে দেওয়া কি ভাল না যেহেতু ভারীগুলি সম্ভবত ধীর হবে?
পিটার

@ দেশপ্রেমিক - আমার বিশ্বাস ন্যূনতম সংখ্যার সাথে 3000 পাউন্ড হ্রাস করার লক্ষ্য। যদিও আপনি অ্যালগরিদমকে 4 ধাপে "n - 29 বারের সাথে ব্যক্তির সাথে অদলবদল করে" পরিবর্তন করতে পারেন যা 30 পোর্কেস্ট সামনের দিকে পাবে, যদিও, ওজনের কঠোরভাবে নয়।
জেমস অ্যান্ডারসন

4

আমি সম্ভবত std::nth_elementভারীতম 20 জনকে লিনিয়ার সময়ে বিভাজন করতে ব্যবহার করব । তারপরে ভারী ভারীতমদের সন্ধানের জন্য এবং মুছতে আরও জটিল পদ্ধতি ব্যবহার করুন।


3

গড় এবং মানক বিচ্যুতি পেতে আপনি তালিকার উপর দিয়ে একটি পাস করতে পারেন, তারপরে যে লোকের যেতে হবে তার সংখ্যা আনুমানিক করতে এটি ব্যবহার করুন। সেই সংখ্যার উপর ভিত্তি করে তালিকাটি তৈরি করতে আংশিক_সোর্ট ব্যবহার করুন। যদি অনুমান কম থাকে তবে নতুন অনুমানের সাথে বাকী অংশগুলিতে আবার আংশিক_সোর্ট ব্যবহার করুন।


3

@ জেমসের মন্তব্যে উত্তর রয়েছে: একটি std::priority_queueযদি আপনি কোনও ধারক ব্যবহার করতে পারেন, বা এর সংমিশ্রণ করতে পারেনstd::make_heap তবে std::pop_heapএবং এর std::push_heapমতো কিছু ব্যবহার করতে চাইলে এবং (এবং ) ব্যবহার করতে পারেন std::vector


2

পাইথনের বিল্ট-ইন হ্যাপক মডিউলটি ব্যবহার করে এখানে একটি হিপ-ভিত্তিক সমাধান রয়েছে। এটি পাইথনে রয়েছে সুতরাং মূল প্রশ্নের উত্তর দেয় না, তবে এটি পোস্ট করা পাইথন সমাধানের চেয়ে ক্লিনার (আইএমএইচও)।

import itertools, heapq

# Test data
from collections import namedtuple

Passenger = namedtuple("Passenger", "name seat weight")

passengers = [Passenger(*p) for p in (
    ("Alpha", "1A", 200),
    ("Bravo", "2B", 800),
    ("Charlie", "3C", 400),
    ("Delta", "4A", 300),
    ("Echo", "5B", 100),
    ("Foxtrot", "6F", 100),
    ("Golf", "7E", 200),
    ("Hotel", "8D", 250),
    ("India", "8D", 250),
    ("Juliet", "9D", 450),
    ("Kilo", "10D", 125),
    ("Lima", "11E", 110),
    )]

# Find the heaviest passengers, so long as their
# total weight does not exceeed 3000

to_toss = []
total_weight = 0.0

for passenger in passengers:
    weight = passenger.weight
    total_weight += weight
    heapq.heappush(to_toss, (weight, passenger))

    while total_weight - to_toss[0][0] >= 3000:
        weight, repreived_passenger = heapq.heappop(to_toss)
        total_weight -= weight


if total_weight < 3000:
    # Not enough people!
    raise Exception("We're all going to die!")

# List the ones to toss. (Order doesn't matter.)

print "We can get rid of", total_weight, "pounds"
for weight, passenger in to_toss:
    print "Toss {p.name!r} in seat {p.seat} (weighs {p.weight} pounds)".format(p=passenger)

যদি কে = টস করার জন্য যাত্রীদের সংখ্যা এবং এন = যাত্রীদের সংখ্যা, তবে এই অ্যালগরিদমের জন্য সবচেয়ে ভাল কেস হ'ল (এন) এবং এই অ্যালগরিদমের জন্য সবচেয়ে খারাপ ক্ষেত্রে হ'ল এনলগ (এন)। সবচেয়ে দীর্ঘস্থায়ী ঘটনাটি ঘটে যদি কে দীর্ঘকাল N এর কাছে থাকে। এখানে সবচেয়ে খারাপ অভিনয়ের উদাহরণ:

weights = [2500] + [1/(2**n+0.0) for n in range(100000)] + [3000]

যাইহোক, এই ক্ষেত্রে (লোকটিকে বিমান থেকে ফেলে দেওয়া (প্যারাশুট সহ, আমি ধারণা করি)) তবে কে অবশ্যই 3000 এরও কম হওয়া উচিত, যা << "কয়েক মিলিয়ন লোক"। গড় রানটাইমটি তাই নলগ (কে) এর সাথে হওয়া উচিত যা লোক সংখ্যার সাথে সমান ar

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.