Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 3.96 KB | None | 0 0
  1. (** Zadanie Przelewanka    **)
  2. (** Autor : Michał Szostek **)
  3. (** Reviewer: Rafał Łyżwa  **)
  4.  
  5. (** Heurystyki **)
  6.  
  7. let rec nwd a b =
  8.   if a = 0 then b
  9.   else if b = 0 then a
  10.   else let (a,b) = (max a b, min a b) in
  11.   nwd (a mod b) b
  12.  
  13. (* Test czy wymagany poziom wody nie jest wyższy od szklanki *)
  14. let test_bucket_size n t_max t_fin =  
  15.   let test = ref true in
  16.   begin
  17.     for i = 0 to (n - 1) do
  18.       if t_max.(i) < t_fin.(i) then test:=false;
  19.     done;
  20.     !test;
  21.   end
  22.  
  23. (* Test czy wszystkie końcowe wysokości są podzielne przez nwd wysokosci szklanek *)
  24. let test_nwd t_max t_fin =
  25.   let nd = Array.fold_left nwd 0 t_max in
  26.   if nd = 0 then true else
  27.   Array.fold_left (fun t a -> t && (a mod nd = 0)) true t_fin
  28.  
  29. (* Test czy jest choć jedna pusta lub pełna (z uwzględnieniem szklanek wysokości zero) *)
  30. let test_empty_or_full n t_max t_fin =
  31.   let test = ref false in
  32.   let only0 = ref true in
  33.   begin
  34.     for i = 0 to (n - 1) do
  35.       if t_max.(i) <> 0 then
  36.       begin
  37.         only0 := false;
  38.         if t_fin.(i) = 0 || t_fin.(i) = t_max.(i) then test := true;
  39.       end;
  40.     done;
  41.     (!test || !only0);
  42.   end
  43.      
  44. (* Główna funkcja sprawdzająca heurystyki *)
  45. let heuristics n t_max t_fin =
  46.   let t1 = test_bucket_size n t_max t_fin in
  47.   let t2 = test_nwd t_max t_fin in
  48.   let t3 = test_empty_or_full n t_max t_fin in
  49.   let heur_array = [|t1;t2;t3|] in
  50.   Array.fold_left (fun t a -> t && a) true heur_array
  51.  
  52. (** Funkcje pomocnicze **)
  53.  
  54. (* Opróżnianie szklanki (i) *)
  55. let empty_bucket state i =
  56.   let t = Array.copy state in
  57.   begin
  58.     t.(i) <- (0);
  59.     t;
  60.   end
  61.  
  62. (* Napełnianie szklanki (i) *)
  63. let fill_bucket state t_max i =
  64.   let t = Array.copy state in
  65.   begin
  66.     t.(i) <- t_max.(i);
  67.     t;
  68.   end
  69.  
  70. (* Przelewanie ze szklanki (i) do szklanki (j) *)
  71. let modify_state state t_max i j =
  72.   let t = Array.copy state in
  73.   let a1 = t.(i) in
  74.   let b1 = t.(j) in
  75.   let b2 = t_max.(j) in
  76.   let d = b2-b1 in
  77.     begin
  78.     t.(i) <- (max 0 (a1 - d));
  79.     t.(j) <- (min b2 (b1 + a1));
  80.     t;
  81.     end  
  82.  
  83. (** Główny algorytm **)
  84.  
  85. let hash stan =
  86.         let wyn = ref 0 in
  87.         Array.iter (fun x -> wyn:= !wyn * 499 + x mod 1000000007) stan;
  88.         (!wyn, stan)
  89.  
  90. (* Główne przeszukiwanie grafu *)
  91. let state_search n t_start t_max t_fin =
  92.   let wyn = ref (-1) in
  93.   let q = Queue.create() in
  94.   let ht = Hashtbl.create 100000 in
  95.   begin
  96.     Queue.add t_start q;
  97.     Hashtbl.add ht (hash t_start) 0;
  98.     while not (Queue.is_empty q) do
  99.       if (Queue.top q) = t_fin then
  100.         begin
  101.         wyn := (Hashtbl.find ht (hash (Queue.top q)));
  102.         Queue.clear q;
  103.         end else
  104.         let top = (Queue.pop q) in
  105.         let k = Hashtbl.find ht (hash top) in
  106.         begin
  107.           for i = 0 to (n-1) do
  108.             begin  
  109.               let e = (empty_bucket top i) in
  110.               if not (Hashtbl.mem ht (hash e)) then
  111.               begin  (* Opróżnianie *)
  112.                 Queue.add e q;
  113.                 Hashtbl.add ht (hash e) (k+1);
  114.               end;
  115.               let e = (fill_bucket top t_max i) in
  116.               if not (Hashtbl.mem ht (hash e)) then
  117.               begin  (* Napełnianie*)
  118.                 Queue.add e q;
  119.                 Hashtbl.add ht (hash e) (k+1);
  120.               end;
  121.               for j = 0 to (n-1) do
  122.                 if i <> j then
  123.                 let e = modify_state top t_max i j in
  124.                 if not (Hashtbl.mem ht (hash e)) then
  125.                 begin  (*Przelwanie*)
  126.                   Queue.add e q;
  127.                   Hashtbl.add ht (hash e) (k+1);
  128.                 end;
  129.               done;
  130.             end;
  131.           done;
  132.         end;
  133.     done;
  134.   !wyn;
  135. end
  136.  
  137. (* Funkcja wynikowa *)
  138. let przelewanka t =
  139. let n = Array.length t in
  140. let t_start = Array.make n 0 in
  141. let t_max = Array.map (fun (a,_) -> a) t in
  142. let t_fin = Array.map (fun (_,b) -> b) t in
  143. if (heuristics n t_max t_fin) then
  144.   state_search n t_start t_max t_fin
  145. else -1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement