Diberi daftar peringkat pemain, saya diharuskan mempartisi pemain (yaitu peringkat) menjadi dua kelompok seadil mungkin. Tujuannya adalah untuk meminimalkan perbedaan antara peringkat kumulatif tim. Tidak ada batasan bagaimana saya dapat membagi pemain menjadi tim (satu tim dapat memiliki 2 pemain dan tim lain dapat memiliki 10 pemain).
Misalnya: [5, 6, 2, 10, 2, 3, 4]
harus kembali([6, 5, 3, 2], [10, 4, 2])
Saya ingin mengetahui algoritme untuk menyelesaikan masalah ini. Harap dicatat saya mengambil kursus pengantar pemrograman online, jadi algoritma sederhana akan dihargai.
Saya menggunakan kode berikut, tetapi karena suatu alasan, pemeriksa kode online mengatakan itu tidak benar.
def partition(ratings):
set1 = []
set2 =[]
sum_1 = 0
sum_2 = 0
for n in sorted(ratings, reverse=True):
if sum_1 < sum_2:
set1.append(n)
sum_1 = sum_1 + n
else:
set2.append(n)
sum_2 = sum_2 + n
return(set1, set2)
Pembaruan: Saya menghubungi instruktur dan saya diberitahu bahwa saya harus mendefinisikan fungsi "pembantu" lain di dalam fungsi untuk memeriksa semua kombinasi yang berbeda maka saya perlu memeriksa perbedaan minimum.
Jawaban:
Catatan: Diedit untuk menangani case dengan lebih baik ketika jumlah semua angka ganjil.
Mundur adalah kemungkinan untuk masalah ini.
Hal ini memungkinkan untuk memeriksa semua kemungkinan secara rekursif, tanpa perlu banyak memori.
Itu berhenti segera setelah solusi optimal ditemukan:, di
sum = 0
manasum
perbedaan antara jumlah elemen himpunan A dan jumlah elemen himpunan B. EDIT: berhenti segerasum < 2
, untuk menangani kasus ketika jumlah semua angka ganjil, yaitu terkait dengan perbedaan minimum 1. Jika jumlah global ini genap, perbedaan min tidak dapat sama dengan 1.Hal ini memungkinkan untuk menerapkan prosedur sederhana pengabaian prematur :
pada waktu tertentu, jika
sum
lebih tinggi maka jumlah semua elemen yang tersisa (yaitu tidak ditempatkan di A atau B) ditambah nilai absolut dari minimum saat ini yang diperoleh, maka kita dapat menyerah memeriksa jalan saat ini, tanpa memeriksa elemen yang tersisa. Prosedur ini dioptimalkan dengan:Ini adalah pseudo-code
Inisialisasi:
a[]
sum_back[i] = sum_back[i+1] + a[i];
min_diff = sum_back[0];
a[0]
A -> indeksi
elemen yang diperiksa diatur ke 1up_down = true;
: boolean ini menunjukkan apakah kita sedang maju (benar) atau mundur (salah)Sementara loop:
If (up_down): maju
sum_back
sum
dengan pilihan iniif (i == n-1)
: LEAF -> tes jika nilai optimal ditingkatkan dan kembali jika nilai baru sama dengan 0 (EDIT:)if (... < 2)
; mundurIf (! Updown): mundur
i == 0
: kembalisum
nilaiBerikut adalah kode, dalam C ++ (Maaf, tidak tahu Python)
sumber
if I == 0
. Saya mengujinya dengan mengganti 10 dengan 11 dalam contoh AndaSaya pikir Anda harus melakukan latihan berikutnya sendiri, kalau tidak Anda tidak belajar banyak. Adapun yang ini, berikut adalah solusi yang mencoba menerapkan saran oleh instruktur Anda:
Keluaran:
Perhatikan bahwa output ini berbeda dari yang Anda inginkan, tetapi keduanya benar.
Algoritma ini didasarkan pada fakta bahwa, untuk memilih semua himpunan bagian yang mungkin dari himpunan yang ditentukan dengan elemen N, Anda dapat menghasilkan semua bilangan bulat dengan bit N, dan memilih item ke-I tergantung pada nilai bit ke-1. Saya meninggalkan Anda untuk menambahkan beberapa baris untuk berhenti segera setelah
best_distance
nol (karena tentu saja tidak bisa lebih baik).Sedikit bit (perhatikan bahwa itu
0b
adalah awalan untuk nomor biner dengan Python):Nomor biner:
0b0111001 == 0·2⁶+1·2⁵+1·2⁴+1·2³+0·2²+0·2¹+1·2⁰ == 57
Bergeser kanan sebanyak 1:
0b0111001 >> 1 == 0b011100 == 28
Kiri bergeser 1:
0b0111001 << 1 == 0b01110010 == 114
Bergeser kanan sebanyak 4:
0b0111001 >> 4 == 0b011 == 3
Bitwise
&
(dan):0b00110 & 0b10101 == 0b00100
Untuk memeriksa apakah bit ke-5 (indeks 4) adalah 1:
(0b0111001 >> 4) & 1 == 0b011 & 1 == 1
Yang diikuti oleh 7 nol:
1 << 7 == 0b10000000
7 yang:
(1 << 7) - 1 == 0b10000000 - 1 == 0b1111111
Semua kombinasi 3-bit:
0b000==0
,0b001==1
,0b010==2
,0b011==3
,0b100==4
,0b101==5
,0b110==6
,0b111==7
(catatan bahwa0b111 + 1 == 0b1000 == 1 << 3
)sumber
Algoritme berikut melakukan ini:
a
, ganjil dalam daftarb
untuk memulaia
danb
jika perubahannya menjadi lebih baikSaya telah menambahkan pernyataan cetak untuk menunjukkan perkembangan pada daftar contoh Anda:
Keluaran:
sumber
Karena saya tahu saya harus membuat semua daftar yang mungkin, saya perlu membuat fungsi "pembantu" untuk membantu menghasilkan semua kemungkinan. Setelah melakukan itu, saya benar untuk memeriksa perbedaan minimum, dan kombinasi daftar dengan perbedaan minimum adalah solusi yang diinginkan.
Fungsi helper bersifat rekursif, dan memeriksa semua kemungkinan kombinasi daftar.
Contoh
r = [1, 2, 2, 3, 5, 4, 2, 4, 5, 5, 2]
:, partisi optimal adalah:([1, 2, 2, 3, 5, 4], [2, 4, 5, 5, 2])
dengan perbedaan1
.r = [73, 7, 44, 21, 43, 42, 92, 88, 82, 70]
, partisi optimal adalah:([73, 7, 21, 92, 88], [44, 43, 42, 82, 70])
dengan perbedaan0
.sumber
Berikut adalah contoh yang cukup rumit, yang dimaksudkan untuk tujuan pendidikan daripada kinerja. Ini memperkenalkan beberapa konsep Python yang menarik seperti daftar pemahaman dan generator, serta contoh yang baik dari rekursi di mana kasus pinggiran perlu diperiksa dengan tepat. Ekstensi, mis. Hanya tim dengan jumlah pemain yang sama yang valid, mudah diimplementasikan dalam fungsi individu yang sesuai.
Keluaran:
sumber
Mengingat Anda menginginkan tim yang merata, Anda tahu skor target dari peringkat masing-masing tim. Ini adalah jumlah peringkat yang dibagi 2.
Jadi kode berikut harus melakukan apa yang Anda inginkan.
Keluaran
Ada pemisahan lain yang memiliki yang sama
fairness
ini semua tersedia untuk menemukan di dalam tuple strong_ratings, saya hanya memilih untuk melihat yang pertama karena ini akan selalu ada untuk daftar peringkat yang Anda lewati (disediakanlen(ratings) > 1
).sumber
Solusi serakah mungkin menghasilkan solusi sub-optimal. Berikut ini adalah solusi serakah yang cukup sederhana, idenya adalah untuk mengurutkan daftar dalam urutan menurun untuk mengurangi efek penambahan peringkat dalam ember. Peringkat akan ditambahkan ke ember yang jumlah total peringkatnya kurang
Keluaran:
Edit:
Pendekatan lain akan menghasilkan semua himpunan bagian yang mungkin dari daftar. Katakanlah Anda memiliki l1 yang merupakan salah satu himpunan bagian dari daftar, maka Anda dapat dengan mudah mendapatkan daftar l2 sehingga l2 = daftar (asli) - l1. Jumlah semua bagian yang mungkin dari daftar ukuran n adalah 2 ^ n. Kita dapat menyatakannya sebagai seq bilangan bulat dari 0 hingga 2 ^ n -1. Ambil contoh, misalkan Anda memiliki list = [1, 3, 5] maka tidak ada kombinasi yang mungkin adalah 2 ^ 3 yaitu 8. Sekarang kita dapat menulis semua kombinasi sebagai berikut:
Larutan:
Keluaran:
sumber