Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Pembahasan OSN 2011 Bongkar Sandi

Pembahasan OSN 2011 Bongkar Sandi

Tweet

More Decks by Catatan Olimpiade Informatika

Other Decks in Programming

Transcript

  1. Pembahasan OSN 2011 Soal 3D ‐ Bongkar Sandi © Mamat

    Rahmat http://olimpiadeinformatika.com
  2. Ringkasan Pak Ganesh lupa suatu sandi yang terdiri dari N

    digit angka Anda boleh bertanya dengan cara menebak sandinya, lalu sistem akan memberi tahu ada berapa digit dari tebakan tersebut yang sudah benar Misal sandi yang benar adalah 129876 dan tebakan anda adalah 123456 maka sistem akan memberikan respon 3 Diberikan batasan banyaknya pertanyaan ﴾tebakan﴿ yang boleh dilakukan, anda harus bisa menemukan sandi yang benar
  3. Subsoal 1 N = 2, maksimal pertanyaan = 100 Coba

    semua kemungkinan sandi 2 digit Banyaknya operasi = 10 = 100 for i := 0 to 9 do for j := 0 to 9 do tebak sandi ij catat respon if (respon = 2) jawab ij selesai N
  4. Subsoal 2 N = 6, maksimal pertanyaan = 55 Bermula

    dari menebak 000000 . Catat responnya sebagai hasil awal. Untuk setiap digit ﴾dari digit pertama hingga digit keenam﴿, kita coba ubah angkanya. Jika ditemukan angka yang menghasilkan respon bertambah dari hasil awal, maka angka tersebut benar. Dalam kasus terburuk, banyaknya operasi = 1+6*9 = 55 for i := 1 to 6 do ans[i] := 0; tebak password 000000; catat responnya sebagai hasil awal for i := 1 to 6 do for j := 1 to 9 do tebak password 000000 dgn digit ke‐i diganti angka j catat respon if (respon > hasil awal) then ans[i] := j; //digit ke‐i adalah j ini break jawab ans[1..6]
  5. Subsoal 3 N = 6, maksimal pertanyaan adalah 25 Mula‐mula,

    lakukan penebakan 000000 , 1111111 , ... , 999999 untuk mendapatkan frekuensi kemunculan angka pada password. Kita definisikan angka‐angka yang mungkin muncul pada digit password ﴾yaitu angka yang frekuensinya > 0﴿ disebut angka spesial. Misalnya untuk password 123432 , angka spesial adalah {1,2,3,4} Dengan hasil di atas, kita tidak perlu mencoba mengganti setiap digit dengan angka 1..9, tetapi cukup menggunakan angka spesial ﴾maksimal 6 angka﴿. Dalam kasus terburuk, banyaknya operasi = 10+6+6+6+6+6+6=46
  6. for i := 0 to 9 do tebak password iiiiii

    catat respon sebagai frek[i] if (frek[i]=0) d := i for i := 1 to 6 do for j := 0 to 9 do if (frek[j] > 0) tebak password dddddd dengan digit ke‐i diganti j catat respon if (respon=1) ans[i] := j; //digit ke‐i adalah j ini break; jawab ans[1..6]
  7. Ide lanjutan 1 Angka spesial yang sudah ditemukan semua posisinya

    dan tidak mungkin muncul di digit selanjutnya tidak perlu dicoba lagi. Caranya, saat suatu angka ditemukan posisinya, kurangi frekuensinya dari array. Dalam kasus terburuk, banyaknya operasi = 10+6+5+4+3+2+1=31 Ide lanjutan 2 Kita tidak perlu mencoba semua angka spesial, tetapi kecualikan satu. Setelah mencoba semua kecuali satu, ternyata tidak ditemukan angka yang benar maka yang dikecualikan itulah yang benar. Dalam kasus terburuk, banyaknya operasi = 10+5+4+3+2+1+0=25
  8. for i := 0 to 9 do tebak password iiiiii

    catat respon sebagai frek[i] if (frek[i]=0) d := i for i := 1 to 6 do for j := 0 to 9 do ‐ if (frek[j] > 0) + if (frek[j] = 0) + continue + if (not(j = angka spesial terakhir)) tebak password dddddd dgn digit ke‐i diganti j catat respon if (respon=1) ans[i] := j //digit ke‐i adalah j ini + frek[j] := frek[j] ‐ 1 break; + else //j adalah angka spesial terakhir + ans[i] := j + frek[j] := frek[j] ‐ 1 jawab ans[1..6]
  9. Subsoal 4 & 5 N = 6, maksimal pertanyaan adalah

    20 Langkah awal sama dengan ide pada subsoal sebelumnya, yaitu menghitung frekuensi dan mendapatkan angka spesial. Ulangi algoritma berikut hingga tersisa 1 angka spesial atau habis : pilih dua angka spesial, sebut saja a dan b Pada langkah awal kita telah mendapatkan hasil dari aaaaaa . Kita sebut ini sebagai hasil dasar. Lalu ganti digit‐digit yang belum tertebak dengan b . Akan ada 3 kemungkinan : hasilnya bertambah, artinya digit tersebut adalah b hasilnya berkurang, artinya digit tersebut adalah a hasilnya tetap, artinya digit tersebut bukan a maupun b Saat tersisa 1 angka spesial, semua digit yang belum tertebak diisi angka tersebut
  10. Dengan algoritma tersebut, pada setiap perulangan kita akan mendapatkan semua

    posisi dari dua angka spesial. Sehingga dibutuhkan maksimal 3x perulangan. Pada kasus terburuk banyaknya interaksi = 10 + 6 + 4 + 2 = 22 Ide Lanjutan Pada langkah awal kita tidak perlu mencoba hingga 999999 . Frekuensi dari 999999 adalah 9 ‐ ﴾total frekuensi digit‐digit sebelumnya﴿ Dalam setiap perulangan, kita tidak perlu mencoba mengganti semua digit yang belum tertebak, tetapi kecualikan satu. Kita dapat menyimpulkan digit terakhir itu dengan membandingkan banyaknya posisi a dan b yang sudah tertebak dengan frekuensinya. Pada kasus terburuk banyaknya interaksi = 9 + 5 + 3 + 1 = 18
  11. for i := 0 to 9 do if (i<9) then

    tebak password iiiiii catat respon sebagai frek[i] else frek[i] = 6 ‐ sum(frek[0..8]) if (frek[i]>0) then masukkan i ke set for i := 1 to 6 do ans[i] := ‐1 // ‐1 artinya digit belum tertebak
  12. while size of set >= 2 do ambil 2 elemen

    dari set sebagai a dan b tota := 0 totb := 0 for i := 1 to 6 do if (ans != ‐1) continue; if not (i = digit terakhir yang belum tertebak) tebak sandi aaaaaa dengan digit ke‐i diganti b catat respon if (respon > frek[a]) then ans[i] := b tota := tota + 1 if (respon < frek[a]) then ans[i] := a totb := totb + 1 else // i adalah digit terakhir yang belum tertebak if tota<frek[a] then ans[i] := a; else if totb<frek[b] then ans[i] := b;
  13. if size of set = 1 then ambil elemen dari

    set sebagai a for i := 1 to 6 do if (ans[i] = ‐1) ans[i] := a jawab ans[1..6]