2013-02-28 30 views
8

iki sayının listeleri ve toplamları bir listesi (belirli bir sırayla yok) arasında listelemek uygun çiftleri kümesini bulma:Verilen özetliyor

a = [1,2,3] 
b = [4,5,6] 
c = [6,7,8] 

nasıl d[k] = (a[i], b[j]) böyle çiftleri d tüm setleri bulabilirsiniz c[k] = a[i] + b[j]'un çiftlerin değiştirilmeden a ve b'den kullanıldığı yerlerdir? c = [7,7,7] için

d = [(1,5), (3,4), (2,6)] 
d = [(2,4), (1,6), (3,5)] 

(bütün listeleri çiftleri olabilir):

d = [(1,6), (2,5), (3,4)] 

(1 cevabı bütün permütasyon esasen eşdeğerdir çünkü)

Ben uzunlukta listeleri ile bu yapmak istiyorum ~ 500, yani bir naif eşleme/geri arama araması söz konusu değil.

+3

Takımdaki her dizinin c dizisiyle eşleşen toplam sayısına sahip bir çift dizi dizisi mi istiyorsunuz? Ayrıca, ilk örnekte, [(1,5), (1,6), (2,6)] - ve daha fazlası gibi - dahil olacak mı? –

+0

Değiştirme yok. Çözmeyi denediğim problem, her bir listenin öğrencilerin puanlarını içermesidir.Her bir listeye ve her ikisinin toplamına erişebiliyorum, ancak toplam puan verildikten sonra, mümkün olan alt puanların ne olduğunu bilmek istiyorum. Sorunu çözmesi daha kolay hale getiriyorsa (veya benzersiz bir çözümün şansını arttırıyorsa), bu listelerin N'sine erişebilirim ve herhangi bir alt kümesi için toplamlar listesi için bir veritabanını sorgulayabilirim. – georgeyiu

+5

Bu sorun Vikipedi'de [Sayısal 3 boyutlu eşleştirme] (http://en.wikipedia.org/wiki/Numerical_3-dimensional_matching) olarak tanımlanmıştır. NP-tamamlandı. –

cevap

0

İşte C++ 'da kaba kuvvet yaklaşımı. Eşdeğerli permütasyonlar oluşturmaz örn. c = [7,7,7] için.

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <utility> 

using namespace std; 

// numerical 3d match: x + y + z = b where                       
// x = a, y = b, z = -c, b = 0                          
template <typename T> 
vector<pair<vector<T>, vector<T> > > n3dmatch(vector<T> a, vector<T> b, vector<T> c) { 
    vector<pair<vector<T>, vector<T> > > result; 
    if (a.size() != b.size() || b.size() != c.size()) return result; 

    vector<vector<T> > ap, bp; 
    sort(a.begin(), a.end()); 
    sort(b.begin(), b.end()); 
    do { ap.push_back(a); } while (next_permutation(a.begin(), a.end())); 
    do { bp.push_back(b); } while (next_permutation(b.begin(), b.end())); 

    for (int i = 0; i < ap.size(); i++) { 
    for (int j = 0; j < ap.size(); j++) { 
     bool match = true; 
     for (int k = 0; k < a.size(); k++) { 
     if ((ap[i][k] + bp[j][k]) != c[k]) { 
      match = false; break; 
     } 
     } 
     if (match) result.push_back({ ap[i], bp[j] }); 
    } 
    } 
    return result; 
} 

int main(int argc, char *argv[]) { 
    vector<int> a = { 1, 2, 3 }; 
    vector<int> b = { 4, 5, 6 }; 
    vector<int> c = { 6, 7, 8 }; 
    //vector<int> c = { 7, 7, 7 };                         
    auto result = n3dmatch(a, b, c); 
    for (int i = 0; i < result.size(); i++) { 
    vector<int> &a = result[i].first; 
    vector<int> &b = result[i].second; 
    for (int j = 0; j < a.size(); j++) cout << a[j] << " "; cout << endl; 
    for (int j = 0; j < b.size(); j++) cout << b[j] << " "; cout << endl; 
    cout << "-" << endl; 
    } 
    return 0; 
} 
1

Tamam, budama ile kaba kuvvet yaklaşımı var. Bu toplam O (N^3)

gösteri kolaylığı için, ben birve b

S: 
+ | 4 5 6 
--|------- 
1 | 5 6 7 
2 | 6 7 8 
3 | 7 8 9 

Ve ben toplamını sahip bir N-by-N meydanına geçeceği c = {6,7,8}
oluşturmak için arıyorum S'da bir '6' buluyorum. Ben Sonra bir '7'

S: 
+ | 4 5 6 
--|------- 
1 |/X/
2 |// 8 
3 | X// 

Solution = { (1,5) (3,4) } 

Ve nihayet '6'

S: 
+ | 4 5 6 
--|------- 
1 |/X/
2 |// X 
3 | X// 

Solution = { (1,5) (3,4) (2,6) } 

1 bulmaya kullanılamaz

S: 
+ | 4 5 6 
--|------- 
1 |/X/
2 | 6/8 
3 | 7/9 

Solution = { (1,5) } 

olarak satır ve sütun çıkarın ve işaretlemek döngü ('6' için olan) devam edecek ve başka bir eşleşme bulacaktır: (2,4). Bu daha sonra ikinci çözümünü oluşturacaktır {(2,4) (1,6) (3,5)}

Şimdi, bunu geliştirmenin bir yolu, bazı dinamik programlama yöntemlerini kullanmaktır: tüm olası kombinasyonları bulmak. sonuç önceden.

Given c={ 6 7 8}, create sets S_x where x is {6,7,8} and 
    S_x = { (i,j) } such that S[i][j]=x 
So: 
    S_6 = { (1,2) (2,1) } 
    S_7 = { (1,3) (2,2) (3,1) } 
    S_8 = { (2,3) (3,2) } 

Ve şimdi, verilen sezgisel tarama ile aynı algoritma O çalışır S_li S_i uzunluğunu göstermektedir (S_l1 * S_l2 * ... S_lN). Bu durumda, bir örnek daha hızlı bir koşuyu daha hızlı çalıştırabilir.

Bu , olabilir. Ayrıca c = {7,7,7} vakasını düzgün bir şekilde ele alacaktır.

Bu benim tüm sahip olduğum neredeyse hepsi.