Bir çizgi segmentinde seyahat röportaj bulmaca


10

Bir sayı uzunluğunda M, burada 0 < M <= 1,000,000,000, N( 1 < N <= 100,000) tamsayı nokta çifti verdiniz . Her bir çiftte, ilk nokta bir nesnenin o anda bulunduğu yeri ve ikinci nokta bir nesnenin nereye taşınması gerektiğini temsil eder. (Unutmayın secondnoktası olabilir küçük daha first).

Şimdi, noktadan başladığınızı 0ve 1nesneyi tutabilen bir arabaya sahip olduğunuzu varsayın . Sayı çizgisi boyunca en küçük mesafeyi katlarken ( yer değiştirme değil ) tüm nesneleri başlangıç ​​konumlarından ilgili son konumlarına taşımak istersiniz . Sonunda noktaya gelmelisin M.

Şimdi, bu sorunu daha basit bir soruna indirgemeye çalışıyorum. Dürüst olmak gerekirse, kaba bir kuvvet ( muhtemelen açgözlü) bir çözüm bile düşünemiyorum . Ancak, ilk düşüncem, iki ileri harekete geri bir hareket dejenere etmekti, ancak bu her durumda işe yaramıyor gibi görünüyor.

Bu 3örnek test örneklerini burada çizdim :http://i.stack.imgur.com/zRv4Q.png

İlk test çantasının cevabı 12. İlk olarak, redöğeyi noktada alırsınız 0. Ardından noktaya 6(distance = 6) gidin, redöğeyi geçici olarak bırakın , ardından greenöğeyi alın. Sonra noktaya 5(distance = 1) hareket edip greenöğeyi bırakıyorsunuz . Daha sonra noktaya 6(distance = 1) geri gidersiniz ve redbıraktığınız öğeyi alırsınız, 9 noktasına (distance = 3) gidin, sonra sırayı bitirmek için point 10(distance = 1) noktasına gidin.

Kat edilen toplam mesafe 6 + 1 + 1 + 3 + 1 = 12, mümkün olan minimum mesafedir.

Diğer iki vakanın cevapları var 12, sanırım. Ancak, bunu çözmek için genel bir kural bulamıyorum.

Kimsenin fikri yok mu?


Yanılmıyorsam, "çakışma" yı saymak için bir veri yapısına ihtiyacınız olmaz mı? Aksi takdirde yanlış çözüyorum.
david

hala işaretleyebilir ve mod kabul ederse yeniden açacak ve göç edecek
cırcır ucube

Soruları siteler arasında otomatik olarak taşıyabiliriz (kapalı olsalar bile), lütfen yayını çaprazlamayın. Bunun yerine, @ ratchetfreak'in tavsiyelerine uyun, ölçülü dikkat için işaretleyin ve sorunun taşınmasını isteyin.
yannis

1
Bu gerçekten uygun görünüyor, ama ya bir kargo parçasına çarpana kadar sağa hareket ederek başlarsanız. O kargoya çarptığınızda, taşıdığınız her şeyi bırakın, o kargoyu alın ve doğru yere koymaya devam edin. Taşınması gereken başka bir yük parçasına çarparsanız, akımı düşürün, alın ve onunla başa çıkın. Kargonuz olmadığında sağa hareket edin.
supersam654

1
Nesneler tüm noktalarda mı yoksa sadece verilenlerde mi var? Belirli bir konumda birden fazla nesne olması mümkün mü? Bir nesneyi geçici olarak sonuncusundan farklı bir yere koymaya izin veriliyor mu?
Sean McSomething

Yanıtlar:


4
  1. Boşsanız, sağa hareket etmeye başlayın.

  2. Ne zaman bir nesneye ulaşırsanız ve boş kalırsanız, onu alın (duh) ve hedefine doğru hareket edin.

  3. Ne zaman bir nesneye ulaşırsanız ave zaten taşırsanız b, her zaman hangi nesnelerden hangisinin sayısal olarak en küçük hedefe sahip olduğunu seçin (en solda).

  4. Henüz M'de değilseniz, 1. adıma geri dönün.

Bu en uygunudur: Gerçek bir seçim yaptığınız tek yer 3. adımdadır. İlk olarak en soldaki hedefi kullanmak, her iki nesneyi gönderdiğiniz zaman mümkün olduğunca sağda olmanızı sağlar.

Neden bu soru programmers.sx dosyasında? Evet, "röportaj sorusu", ama bu sadece güzel bir bilmece.

PS. Uygulama açısından, ihtiyacınız olan tek şey orijinal konuma göre sıralanmış görevlerin (tam sayı nokta çiftleri) listesidir.


1

Bu hareketlerin size verildiğini varsayalım, (a, b), (c, d), (e, f), ...o zaman seyahat etmeniz gereken minimum mesafe ve seyahat abs(b - a) + abs(d - c) + abs(f - e) + ...ettiğiniz gerçek mesafedir abs(b - a) + abs(c - b) + abs(d - c) + abs(e - d) + ....
Temel olarak, bir dizi hamle verildiğinde nokta, öğeleri değiştirerek "hareket mesafesi" işlevini en aza indirmektir. Belirli bir kombinasyonu bir düğüm olarak ve ondan ulaşabileceğiniz tüm kombinasyonları kenar olarak görüyorsanız, bir sezgisel tarama kullanan birçok grafik arama algoritmasından birini kullanabilirsiniz. Bir örnek ışın aramadır .


0

Belki sorunu yanlış anlıyorum ama aşağıdakilere ne dersiniz:

  1. Çiftleri geçerli konum olan çiftin ilk sayısına göre sıralayın
  2. Satır değiştirme öğelerini uygun konumlarına taşıyın (temp değişkeniniz var)

Sıralanmış olması, öğeleri uygun konuma yerleştirmek için ileri geri gitmemenizi garanti eder (satır bir dizi veya liste olarak temsil edilip edilmediğine bakılmaksızın)

@Templatetypedef yorumundan sonra güncelle: Tüm çiftleri saklamak için
a öğesini kullanın HashTable. Her bir çiftin geçerli konumunu dizin anahtarı olarak kullanın.
Çiftler üzerinde ikinci bir dizin kullanın.

 1. Get next pair according to index from the line.
 2. If current pair exists in hashtable then place element to its target location.  
    2.a Remove pair from hashtable.  
    2.b Make current pair the target location. Then go to step 1  
 ELSE 
        Increment current index until you get a pair present in the hashtable. Go to step 2  

Her seferinde sadece bir birim taşıyabilirsiniz, birçok kez yolunuzu geri çekmeniz gerektiğini düşünüyorum
david

Seni gerçekten takip etmiyorum.İhtiyaç sadece ileri gitmek ve sayıları takas etmek gibi görünüyor.Geçerli konumu ve hedef konumu zaten biliyorsunuz.Sadece onları değiştirin (dediğiniz gibi cart değişkenini kullanarak) ve sonraki çift
user10326

Bu karşı örneği düşünün: (1, 10), (10, 1), (2, 3), (3, 4). Bunu yapmanın en iyi yolu, nesneyi 1 10 pozisyonuna taşımak, sonra nesneyi 10 pozisyonunda almak ve 1 pozisyonuna taşımak, daha sonra 2'yi 3'e ve 3'ü 4'e taşımaktır. başlangıç ​​pozisyonu 1'i 10'a taşıyacak, sonra 2'ye 3'ü, 3'ü 4'e taşımak için sonuna kadar geri dönecek, daha sonra 10'u almak ve getirmek için sonuna kadar gidecekti. geri döndü.
templatetypedef

@templatetypedef: Ne demek istediğini anlıyorum.Geçmiş cevap
user10326

Güncel cevabınızda, "mevcut indeks" sadece mevcut pozisyonu mu gösteriyor?
david

0

Temelde açgözlü bir algoritmaya olan eğilimim:

Taşınması gereken noktaların bir listesini oluşturun. Bunu optimize etmek gerekli sorunun bir parçası olmadığından, onu organize etme konusunda endişelenmeyeceğim.

while !Done
    if CartIsEmpty()
        FindClosestObjectToMove()
        MoveToObject()
       LoadCart()
    else
        Destination = Cart.Contains.Target
        CurrentMove = [Location, Destination]
        SubList = List.Where(Move.Within(CurrentMove))
        if !SubList.Empty
            Destination = SubList.FindSmallest(Location, Move.Origin)
        MoveTo(Destination)
        if !Destination.Empty
            SwapCart()
            UpdateTaskList()
        else
            EmptyCart()
            DeleteTask()

Bence bu bütün davaları kapsıyor. Bir anlamda özyinelemeli ama kendini güncellemek yerine listeyi güncelleyerek


Cevap için teşekkürler. Açıklayabilir Destination = SubList.FindSmallest(Location, Move.Origin)misiniz? Neyi Move.Origintemsil eder?
david

Move.Origin, taşınacak nesnenin bulunduğu konumdur - başlangıç ​​noktasıdır. Temel olarak, bir hamleye bakarken, ilk önce yayılma alanı içindeki daha küçük hamleleri yapın.
Loren Pechtel

-1

Bu asimetrik gezici satıcı problemidir . Bunu bir grafik olarak düşünebilirsiniz. Kenarlar her bir (başlat, bitir) çifti, her biri için bir (0, başlangıç) ve diğer tüm (bitir, başlat) çiftleri olacaktır.

NP! = P olduğu varsayılarak, üstel bir beklenen çalışma süresi olacaktır.


3
Bunun doğru olduğundan emin değilim. Bu özel bir asimetrik TSP vakasıdır, bu nedenle polinom-zaman çözümü olabilir.
templatetypedef

MSayı çizgisinin bitiş noktası nerede (bitiş, M) gibi bir kenara ihtiyacınız yok ?
david

Ayrıca, üstel bir algoritma çok yavaştır, çünkü N100.000 olabilir.
david

Bu ifadeyi desteklemek için, muhtemelen her asimetrik gezici satıcı problemini bu tanımın eşdeğer bir problemine dönüştürme yönteminiz var mı?
dan_waterworth

1
Eşdeğer değil. Gezgin satıcı grafiğin tüm köşelerini ziyaret etmelidir. Formülasyonunuz tüm kenarlarını ziyaret etmesini gerektirir.
alexis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.