Advertisement
rplantiko

Ein Knapsack-Problem

Aug 26th, 2021 (edited)
3,490
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ABAP 2.98 KB | None | 0 0
  1. *&---------------------------------------------------------------------*
  2. *& Report ZZ_OPT_KNAPSACK
  3. *&---------------------------------------------------------------------*
  4. *& Versucht, eine Teilmenge des Multi-Sets PARTS so zu addieren,
  5. *& daß die Summe möglichst nahe an p_result herankommt, sie aber nicht
  6. *& übersteigt
  7. *&---------------------------------------------------------------------*
  8. report zz_opt_knapsack_rpl.
  9.  
  10. parameters:
  11.   p_result type i default 50,
  12.   p_parts  type string default `25, 20, 15, 10, 5, 2`.
  13.  
  14.  
  15. class lcl_opt definition.
  16.   public section.
  17.  
  18. * Behälter für eine Summe und eine Zahlenmenge
  19.     types:
  20.       begin of ty_parts_sum,
  21.         parts type int4_table,
  22.         sum   type i,
  23.       end of ty_parts_sum.
  24.  
  25.     class-methods:
  26.       start,
  27.       get_best
  28.         importing is_input      type ty_parts_sum
  29.         returning value(es_opt) type ty_parts_sum.
  30. endclass.
  31.  
  32. class lcl_opt implementation.
  33.   method start.
  34.  
  35. * Vorbereitung
  36.     condense p_parts no-gaps.
  37.     split p_parts at ',' into table data(lt_parts).
  38.  
  39. * Ausführung
  40.     data(ls_opt) = get_best( value #(
  41.       parts = conv #( lt_parts )
  42.       sum   = p_result
  43.     ) ).
  44.  
  45. * Ergebnis ausgeben
  46.     sort ls_opt-parts descending.
  47.     lt_parts = value #( for i in ls_opt-parts ( condense( conv string( i ) ) ) ).
  48.     write: /
  49.       ls_opt-sum no-gap, ':',
  50.       concat_lines_of( table = lt_parts sep = `+` ).
  51.  
  52.   endmethod.
  53.   method get_best.
  54.  
  55.     loop at is_input-parts into data(lv_part)
  56.       where table_line = is_input-sum.
  57. * Triviale Lösung gefunden
  58.       es_opt = value #(
  59.         sum   = is_input-sum
  60.         parts = value #( ( lv_part ) )
  61.       ).
  62.       return.
  63.     endloop.
  64.  
  65. * Nicht-triviale Lösungen
  66.     loop at is_input-parts into lv_part
  67.       where table_line < is_input-sum.
  68.       data(lv_tabix) = sy-tabix.
  69.  
  70. * Wir entfernen je ein Element und rekurrieren
  71.       data(ls_input) = is_input.
  72.       delete ls_input-parts index sy-tabix.
  73.       subtract lv_part from ls_input-sum.
  74.       if lines( ls_input-parts ) > 1.
  75. * Tabelle hat noch mehr als 1 part - Rekursion:
  76.         data(ls_opt) = get_best( ls_input ).
  77.       elseif lines( ls_input-parts ) = 1.
  78. * Nur 1 Teil, dann gibt es nur diese triviale Lösung:
  79.         ls_opt = value #(
  80.           sum   = ls_input-parts[ 1 ]
  81.           parts = ls_input-parts ).
  82.       else.
  83. * Null Teile
  84.         clear ls_opt.
  85.       endif.
  86.  
  87. * Das herausgenommene Part wieder hinzufügen
  88.       append lv_part to ls_opt-parts.
  89.       add lv_part to ls_opt-sum.
  90.  
  91. * Schauen, was herauskam:
  92.       if ls_opt-sum = is_input-sum.
  93. * Exakter Match gefunden
  94.         es_opt = ls_opt.
  95.         return.
  96.       elseif ls_opt-sum < is_input-sum.
  97. * Beste Annäherung an is_input-sum in es_opt merken
  98.         if es_opt is initial.
  99.           es_opt = ls_opt.
  100.         elseif ls_opt-sum > es_opt-sum.
  101.           es_opt = ls_opt.
  102.         endif.
  103.       endif.
  104.  
  105.     endloop.
  106.  
  107.   endmethod.
  108. endclass.
  109.  
  110.  
  111. start-of-selection.
  112.   lcl_opt=>start( ).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement