pengantar
Ada seorang pemungut pajak yang mengalami kesulitan mengelola pajak kerajaannya: catatan sejarah telah terbakar dalam api besar.
Dia ingin mencari tahu berapa banyak masa lalu yang mungkin ada dalam hal di mana uang saat ini diwarisi dari. Untungnya, kerajaannya sangat sederhana.
Kerajaan dapat dimodelkan dengan matriks boolean 2D, di mana l
mewakili seseorang yang telah mewarisi uang, dan O
mewakili seseorang yang belum. Sebagai contoh:
l O l l
O O O l
l O l O
O O O l
(Ini akan selalu menjadi persegi panjang)
Pada generasi berikutnya, kerajaan lebih kecil (Serigala kuat!).
Generasi berikutnya akan terlihat seperti ini, ditumpangkan pada generasi sebelumnya ( x
adalah pengganti bagi keturunan di generasi berikutnya)
l O l l
x x x
O O O l
x x x
l O l O
x x x
O O O l
Sebuah keturunan akan melihat nenek moyang yang secara langsung di sekitar mereka (Jadi atas meninggalkan x
akan melihat { l
, O
, O
, O
}, disebut lingkungan persegi panjang unaligned )
Jika hanya satu leluhur yang mewarisi uang, keturunan akan mewarisi uang dari mereka. Jika lebih dari satu leluhur memiliki uang warisan, mereka akan bertengkar dan keturunannya tidak akan mewarisi uang. Jika tidak ada yang mewarisi uang, keturunannya tidak akan mewarisi uang.
(Lebih dari satu keturunan dapat mewarisi dari satu leluhur)
Jadi, generasi berikutnya akan terlihat seperti:
l l O
l l O
l l O
Tantangan
Memasukkan
Keadaan saat ini dari generasi, sebagai array array dari dua nilai berbeda, di mana array dalam semua memiliki panjang yang sama.
Misalnya, untuk contoh di atas, bisa jadi:
[
[True, True, False],
[True, True, False],
[True, True, False]
]
Keluaran
Integer mewakili jumlah generasi unik sebelumnya di mana generasi berikutnya adalah input.
Anda dapat mengasumsikan bahwa jawabannya akan selalu kurang dari 2 ^ 30 - 1. (atau 1073741823).
Generasi sebelumnya akan disebut "preimage" dan tantangan ini adalah menghitung preimage .
Mencetak gol
Ini adalah tantangan kode tercepat , sehingga setiap pengiriman akan diuji di komputer saya, dan pengiriman yang membutuhkan waktu paling sedikit akan menjadi pemenang.
Contoh Input dan Output
(Di mana 1
keturunan yang mewarisi uang, dan 0
merupakan keturunan yang tidak mewarisi uang)
Memasukkan:
[[1, 0, 1],
[0, 1, 0],
[1, 0, 1]]
Keluaran:
4
Memasukkan:
[[1, 0, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 1, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 1, 1, 1]]
Keluaran:
254
Memasukkan:
[[1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 1, 1, 0, 0]]
Keluaran:
11567
sumber
Jawaban:
C ++ menggunakan perpustakaan BuDDy
Ini sepertinya alasan yang bagus untuk bermain dengan diagram keputusan biner . Kerajaan diubah menjadi formula boolean besar di mana kita harus menghitung jumlah cara yang bisa dipenuhi. Itu bisa (kadang-kadang) dilakukan lebih efisien daripada yang terdengar.
Kerajaan harus diberikan sebagai program konstan sebagai array datar dan dimensi yang diberikan secara eksplisit. (Masukan bagus dibiarkan sebagai eksekusi untuk pembaca :-)
Berikut adalah kode sederhana yang memalukan:
Untuk mengkompilasi dengan debian 8 (jessie), instal
libbdd-dev
dan lakukang++ -std=c++11 -o hist hist.cpp -lbdd
. (Opsi pengoptimalan hampir tidak membuat perbedaan karena pekerjaan nyata dilakukan di perpustakaan.)Contoh besar dapat menyebabkan pesan tentang pengumpulan sampah. Mereka bisa ditekan, tetapi saya lebih suka melihat mereka.
bdd_satcount
mengembalikan adouble
, tapi itu cukup baik untuk rentang hasil yang diharapkan. Teknik penghitungan yang sama dimungkinkan dengan bilangan bulat (besar) yang tepat.Kode dioptimalkan untuk
ROWS<COLS
. Jika Anda memiliki lebih banyak baris daripada kolom, mungkin ide yang baik untuk memindahkan matriks.sumber
Python 2.7
Ini hanya upaya pertama yang naif. Ini tidak terlalu cepat, tetapi itu benar.
Pengamatan pertama adalah bahwa setiap sel bergantung pada empat sel pada generasi sebelumnya. Kita dapat mewakili keempat sel itu sebagai angka 4-bit (0-15). Menurut aturan, jika persis satu sel tetangga pada generasi sebelumnya
1
, maka sel yang diberikan pada generasi saat ini adalah1
, jika tidak, itu akan menjadi0
. Itu sesuai dengan kekuatan dua, yaitu[1, 2, 4, 8]
,. Ketika keempat leluhur diwakili sebagai angka 4-bit, angka lainnya akan menghasilkan dalam0
generasi saat ini. Dengan informasi ini, setelah melihat sel dalam generasi saat ini, kita dapat mempersempit kemungkinan lingkungan pada generasi sebelumnya menjadi satu dari empat atau satu dari dua belas kemungkinan masing-masing.Saya memilih untuk mewakili lingkungan sebagai berikut:
di mana 0 adalah bit paling tidak signifikan, dan seterusnya.
Pengamatan kedua adalah bahwa untuk dua sel yang berdekatan pada generasi saat ini, dua lingkungan dari generasi sebelumnya tumpang tindih:
atau:
Dalam kasus horizontal, dari
2
dari lingkungan kiri tumpang tindih dengan dari3
dari lingkungan kanan, dan juga dengan0
di kiri dan1
di kanan. Dalam kasus vertikal,1
dari lingkungan atas tumpang tindih dengan3
dari lingkungan bawah, dan juga dengan0
di atas dan2
di bawah.Tumpang tindih ini berarti bahwa kita dapat mempersempit kemungkinan untuk lingkungan yang belum dipilih berdasarkan apa yang telah kita pilih. Kode berfungsi dengan cara dari kiri ke kanan, atas ke bawah, dalam pencarian mendalam-pertama secara rekursif untuk kemungkinan preimage. Diagram berikut menunjukkan lingkungan mana yang sebelumnya harus kita pertimbangkan ketika melihat lingkungan yang mungkin dari sel saat ini:
Berikut kodenya:
Untuk menjalankannya:
sumber
O(<something>^n)
saya.)