LukasRiedel

ADS - Kůň

Apr 14th, 2017
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.83 KB | None | 0 0
  1. /*
  2.  * Na jisté šachovnici žil kulhavý kůň.
  3.  * To je zvláštní šachová figurka, která v sudých tazích táhne jako jezdec, v lichých jako pěšec.
  4.  * Vymyslete algoritmus, který z jednoho zadaného políčka dokulhá na druhé na nejmenší možný počet tahů.
  5.  */
  6.  
  7. using System;
  8. using System.Collections.Generic;
  9.  
  10. namespace KulhavyKun
  11. {
  12.     class Pozice : IEquatable<Pozice>
  13.     {
  14.         public int X;
  15.         public int Y;
  16.         public int pocitadlo;
  17.         public Pozice() {  }
  18.         public Pozice(int X, int Y, int pocitadlo) { this.X = X; this.Y = Y; this.pocitadlo = pocitadlo; }
  19.         public bool Equals (Pozice pozice) { return pozice.X == X && pozice.Y == Y; }
  20.     }
  21.     class Program
  22.     {
  23.         // Šachovnici budu indexovat z levého horního rohu, tedy od 0 do 7 na obou osách.        
  24.  
  25.         static Pozice KamMuzeJitPesec(Pozice odkud) // Metoda rozhoduje, na jakou pozici se může přesunout pěšec. Je vždy jen jedna (nebo žádná).
  26.         {
  27.             return odkud.Y == 0 ? null : new Pozice(odkud.X, odkud.Y - 1, odkud.pocitadlo + 1); // Když se nacházíme v "prvním řádku", cesta neexistuje. Zde výpočet této cesty končí.
  28.         }
  29.  
  30.         static List<Pozice> KamMuzeJitJezdec(Pozice odkud) // Metoda rozhoduje, na jakou pozici se může přesunout jezdec.
  31.         {
  32.             List<Pozice> kam = new List<Pozice>();
  33.  
  34.             // "Doleva nahoru"
  35.             if (odkud.X - 1 >= 0 && odkud.Y - 2 >= 0) { kam.Add(new Pozice(odkud.X - 1, odkud.Y - 2, odkud.pocitadlo + 1)); }
  36.             if (odkud.X - 2 >= 0 && odkud.Y - 1 >= 0) { kam.Add(new Pozice(odkud.X - 2, odkud.Y - 1, odkud.pocitadlo + 1)); }
  37.  
  38.             // "Doprava nahoru"
  39.             if (odkud.X + 1 <= 7 && odkud.Y - 2 >= 0) { kam.Add(new Pozice(odkud.X + 1, odkud.Y - 2, odkud.pocitadlo + 1)); }
  40.             if (odkud.X + 2 <= 7 && odkud.Y - 1 >= 0) { kam.Add(new Pozice(odkud.X + 2, odkud.Y - 1, odkud.pocitadlo + 1)); }
  41.  
  42.             // "Doleva dolů"
  43.             if (odkud.X - 1 >= 0 && odkud.Y + 2 <= 7) { kam.Add(new Pozice(odkud.X - 1, odkud.Y + 2, odkud.pocitadlo + 1)); }
  44.             if (odkud.X - 2 >= 0 && odkud.Y + 1 <= 7) { kam.Add(new Pozice(odkud.X - 2, odkud.Y + 1, odkud.pocitadlo + 1)); }
  45.  
  46.             // "Doprava dolů"
  47.             if (odkud.X + 1 <= 7 && odkud.Y + 2 <= 7) { kam.Add(new Pozice(odkud.X + 1, odkud.Y + 2, odkud.pocitadlo + 1)); }
  48.             if (odkud.X + 2 <= 7 && odkud.Y + 1 <= 7) { kam.Add(new Pozice(odkud.X + 2, odkud.Y + 1, odkud.pocitadlo + 1)); }
  49.  
  50.             return kam.Count == 0 ? null : kam; // Pokud se z dané pozice nemůžeme s jezdcem nikam dostat, výpočet této cesty zde končí.
  51.         }
  52.         static void Main(string[] args)
  53.         {
  54.             Pozice odkud = new Pozice(5, 6, 0);
  55.             Pozice kam = new Pozice(7, 0, 0);
  56.  
  57.             Queue<Pozice> Fronta = new Queue<Pozice>();
  58.             Fronta.Enqueue(odkud); // BFS začneme v bodě, ve kterém se nachází náš kulhavý kůň.
  59.  
  60.             bool[,] Flags = new bool[8, 8]; // Zavedeme si značkovací pole, abychom věděli, kde jsme již byli a abychom se tak necyklili.
  61.  
  62.             Pozice aktualni;
  63.  
  64.             // Jedná se o klasické BFS s tím, že si u každé pozice pamatujeme, na kolik kroků jsme se tam dostali. Složitost by měla být O(n), kde n je počet vrcholů šachovnce. Tedy 64.
  65.             while (!(aktualni = Fronta.Dequeue()).Equals(kam)) // Budeme iterovat do doby, dokud nedojdeme do chtěného umístění. Řekl bych, že taková cesta existuje vždy.
  66.             {
  67.                 Flags[aktualni.X, aktualni.Y] = true;
  68.                 if (aktualni.pocitadlo % 2 == 0 && KamMuzeJitJezdec(aktualni) != null)
  69.                     foreach (Pozice pozice in KamMuzeJitJezdec(aktualni)) if (!Flags[pozice.X, pozice.Y])
  70.                             Fronta.Enqueue(pozice); else ;
  71.                 else if (aktualni.pocitadlo % 2 != 0 && KamMuzeJitPesec(aktualni) != null && !Flags[KamMuzeJitPesec(aktualni).X, KamMuzeJitPesec(aktualni).Y])
  72.                     Fronta.Enqueue(KamMuzeJitPesec(aktualni));
  73.                 else continue;
  74.             }
  75.  
  76.             Console.WriteLine(aktualni.pocitadlo);
  77.         }
  78.     }
  79. }
  80.  
  81. /*
  82.  * A ještě k tomu, že se můžeme z dané pozice dostat kamkoliv.
  83.  * Důkaz provedeme rozborem případů.
  84.  * Představme si, že se nacházíme ve vrcholu a chceme jít doprava - pak stačí pohnout pěšcem, skočit koněm doprava dolů a opět pohout pěšcem.
  85.  * Obdobně pro případy, kdy chceme jít doleva nebo šikmo.
  86.  * Pokud chceme jít dopředu, logicky stačí jen pohnout pěšcem.
  87.  * Pokud chceme jít dolů, stačí skočit koněm BÚNO doleva dolů a pak doprava dolů. Zbytek kroků doplníme pěšci.
  88.  * Podobně by se daly nasimlovat všechny krajní případy.
  89.  *
  90.  * PS: Doufám, že jsem právě nedokázal něco, co není pravda.
  91.  */
Advertisement
Add Comment
Please, Sign In to add comment