Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2020
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.55 KB | None | 0 0
  1. #include <algorithm>
  2. #include <queue>
  3. #include <unordered_map>
  4. #include <unordered_set>
  5. #include <iostream>
  6. #include <fstream>
  7. #include <string>
  8.  
  9. using namespace std;
  10.  
  11. ////////////////////////////////////////////////////////////////
  12. //TYPES
  13. ///////////////////////////////////////////////////////////////
  14.  
  15. //data
  16. struct Library;
  17.  
  18. //logic
  19. class Scanner;
  20.  
  21. //output
  22. struct LibOutput;
  23. using Output = std::unordered_map<int, LibOutput>;
  24.  
  25. ////////////////////////////////////////////////////////////////
  26. //Functions
  27. ////////////////////////////////////////////////////////////////
  28.  
  29. /*Median of all books scores*/
  30. double GetMedian();
  31.  
  32. ////////////////////////////////////////////////////////////////
  33. //GLOBALS
  34. ////////////////////////////////////////////////////////////////
  35.  
  36. //counters
  37. int g_DaysNum, g_BooksNum, g_LibrariesNum;
  38.  
  39. //books
  40. struct
  41. {
  42.     vector<int> Scores;
  43.     //vector<vector<int>> Libraries;
  44.     //vector<bool> ScannedFlags;
  45. } g_Books;
  46. #define SCORE(id) g_Books.Scores[id]
  47.  
  48. //libraries
  49. vector<Library> g_Libraries;
  50. #define LIBRARY(id) g_Libraries[(id)]
  51.  
  52.  
  53. ////////////////////////////////////////////////////////////////
  54. //IMPLEMENTATIONS
  55. ////////////////////////////////////////////////////////////////
  56.  
  57. struct BookScoreComp
  58. {
  59.     bool operator()(int lbi, int rbi) const
  60.     {
  61.         const int lScore = SCORE(lbi);
  62.         const int rScore = SCORE(rbi);
  63.  
  64.         if (lScore < rScore)
  65.             return true;
  66.         else if (lScore > rScore)
  67.             return false;
  68.  
  69.         return lbi > rbi;
  70.     }
  71. };
  72.  
  73. struct LibOutput
  74. {
  75.     vector<int> Books;
  76.  
  77.     void Write(std::ostream& out, int libId) const
  78.     {
  79.         out << libId << " " << Books.size() << endl;
  80.         for (int bookId : Books)
  81.             out << bookId << " ";
  82.         out << endl;
  83.     }
  84. };
  85.  
  86. struct Library
  87. {
  88.     Library(int id, vector<int>&& bookIds, int signUpDays, int booksPerDay)
  89.         : Id(id)
  90.         , BookIds(std::move(bookIds))
  91.         , SignUpDays(signUpDays)
  92.         , BooksPerDay(booksPerDay)
  93.     {
  94.         TotalScore = 0;
  95.         for (int bookId : BookIds)
  96.             TotalScore += SCORE(bookId);
  97.     }
  98.  
  99.  
  100.     const int Id;
  101.     vector<int> BookIds;
  102.     const int SignUpDays;
  103.     const int BooksPerDay;
  104.  
  105.     long long TotalScore;
  106.  
  107.     inline int GetNextBookId() const { return GetRemainingBooksCount() > 0 ? BookIds[nextScanBookIdx] : -1; }
  108.     inline int GetRemainingBooksCount() const { return BookIds.size() - nextScanBookIdx; }
  109.  
  110.     int GetExtendedBookScore(int remainingBooksToday) const
  111.     {
  112.         if (nextScanBookIdx + remainingBooksToday >= BookIds.size())
  113.             return 0;
  114.  
  115.         return SCORE(BookIds[nextScanBookIdx + remainingBooksToday]);
  116.     }
  117.  
  118.     inline int GetDailyScans() const
  119.     {
  120.         return std::min(GetRemainingBooksCount(), BooksPerDay);
  121.     }
  122.  
  123.     void AdvanceBook(int bookId)
  124.     {
  125.         int bookIdx = nextScanBookIdx;
  126.         while (BookIds[bookIdx] != bookId)
  127.             ++bookIdx;
  128.  
  129.         std::swap(BookIds[bookIdx], BookIds[nextScanBookIdx]);
  130.  
  131.         if (nextScanBookIdx < BookIds.size())
  132.             ++nextScanBookIdx;
  133.     }
  134.  
  135. private:
  136.     int nextScanBookIdx = 0;
  137. };
  138.  
  139. class Scanner
  140. {
  141.     using LibScansMap = std::unordered_map<int, int>;
  142.     using BookMap = std::unordered_map<int, vector<int>>;
  143.  
  144. public:
  145.     //Statistic methods
  146.     inline bool IsNewBook(int bookId) const { return m_BookStates[bookId] == BookState::New; }
  147.     inline bool IsPendingBook(int bookId) const { return m_BookStates[bookId] == BookState::Pending; }
  148.  
  149.     long long GetTotalBooksToday() const
  150.     {
  151.         long long totalBooks = 0;
  152.         for (int libId : m_Libraries)
  153.         {
  154.             totalBooks += LIBRARY(libId).GetDailyScans();
  155.         }
  156.  
  157.         return totalBooks;
  158.     }
  159.  
  160.     double GetScansAverageToday() const
  161.     {
  162.         return (double)GetTotalBooksToday() / (double)m_Libraries.size();
  163.     }
  164.  
  165. public:
  166.     Scanner() : m_BookStates(g_BooksNum, BookState::New) {};
  167.  
  168.     void DoOutput(ostream& outStream) const
  169.     {
  170.         size_t libsCount = std::count_if(m_Output.cbegin(), m_Output.cend(), [](Output::const_reference elem) {return !elem.second.Books.empty(); });
  171.         outStream << libsCount << endl;
  172.  
  173.         for (int libId : m_Libraries)
  174.         {
  175.             auto& outputEntry = m_Output.at(libId);
  176.             if (!outputEntry.Books.empty())
  177.                 outputEntry.Write(outStream, libId);
  178.         }
  179.     }
  180.  
  181.     void AddLibrary(int libraryId)
  182.     {
  183.         auto& library = LIBRARY(libraryId);
  184.         InitLibrary(library);
  185.  
  186.         if (library.GetRemainingBooksCount() <= 0)
  187.             return;
  188.  
  189.         m_Libraries.push_back(libraryId);
  190.         const auto& books = library.BookIds;
  191.         for (int bookId : books)
  192.         {
  193.             m_BookToLibraries[bookId].push_back(libraryId);
  194.             m_BookStates[bookId] = BookState::Pending;
  195.         }
  196.     }
  197.  
  198.     void ScanBooks()
  199.     {
  200.         LibScansMap libraryScans;
  201.         for (int libId : m_Libraries)
  202.         {
  203.             auto booksScans = LIBRARY(libId).GetDailyScans();
  204.             if (booksScans > 0)
  205.                 libraryScans[libId] = booksScans;
  206.         }
  207.  
  208.         while (!libraryScans.empty())
  209.         {
  210.             int optimalLibId = GetOptimalLibId(libraryScans);
  211.  
  212.             int bookId = LIBRARY(optimalLibId).GetNextBookId();
  213.             m_Output[optimalLibId].Books.push_back(bookId);
  214.  
  215.             if (m_BookStates[bookId] == BookState::Scanned)
  216.             {
  217.                 int nz = 0;
  218.             }
  219.  
  220.             m_BookStates[bookId] = BookState::Scanned;
  221.             for (int libId : m_BookToLibraries.at(bookId))
  222.             {
  223.                 auto& library = LIBRARY(libId);
  224.                 library.AdvanceBook(bookId);
  225.  
  226.                 auto it = libraryScans.find(libId);
  227.                 if (it != libraryScans.end())
  228.                 {
  229.                     it->second = std::min(it->second, library.GetRemainingBooksCount());
  230.                     if (--(it->second) <= 0)
  231.                         libraryScans.erase(it);
  232.                 }
  233.             }
  234.         }
  235.     }
  236.  
  237. private:
  238.     int GetOptimalLibId(LibScansMap& remainingScans) const
  239.     {
  240.         auto optimalIt = remainingScans.end();
  241.  
  242.         int maxScore = INT_MIN;
  243.         int minBonus = INT_MAX;
  244.         int minId = g_LibrariesNum;
  245.  
  246.         for (auto it = remainingScans.begin(); it != remainingScans.end(); ++it)
  247.         {
  248.             auto& library = LIBRARY(it->first);
  249.             int score = SCORE(library.GetNextBookId());
  250.             int bonus = library.GetExtendedBookScore(it->second);
  251.             int id = library.Id;
  252.  
  253.             if (score > maxScore || (score == maxScore && bonus < minBonus) || (score == maxScore && bonus == minBonus && id < minId))
  254.             {
  255.                 optimalIt = it;
  256.                 maxScore = score;
  257.                 minBonus = bonus;
  258.                 minId = id;
  259.             }
  260.         }
  261.  
  262.         return optimalIt->first;
  263.     }
  264.  
  265.     void InitLibrary(Library& library)
  266.     {
  267.         static BookScoreComp scoreComparator;
  268.  
  269.         auto newEnd = std::remove_if(library.BookIds.begin(), library.BookIds.end(), [this](int bookId) { return m_BookStates[bookId] == BookState::Scanned; });
  270.         std::sort(library.BookIds.begin(), newEnd, [](int lbi, int rbi) { return scoreComparator(rbi, lbi); });
  271.         library.BookIds.erase(newEnd, library.BookIds.end());
  272.     }
  273.  
  274. private:
  275.     Output m_Output;
  276.  
  277.     BookMap m_BookToLibraries;
  278.  
  279.     std::vector<int> m_Libraries;
  280.  
  281.     enum class BookState
  282.     {
  283.         New,
  284.         Pending,
  285.         Scanned
  286.     };
  287.     std::vector<BookState> m_BookStates;
  288. };
  289.  
  290. void DoInput(string& inputFile)
  291. {
  292.     cin >> inputFile;
  293.  
  294.     ifstream in("test/" + inputFile + ".txt", ios::in);
  295.  
  296.     if (in.is_open() == false) {
  297.  
  298.         cout << "Couldn't open the file!" << endl;
  299.         return;
  300.     }
  301.  
  302.     in >> g_BooksNum;
  303.     in >> g_LibrariesNum;
  304.     in >> g_DaysNum;
  305.  
  306.  
  307.     g_Books.Scores.resize(g_BooksNum);
  308.     for (int& score : g_Books.Scores)
  309.     {
  310.         in >> score;
  311.     }
  312.  
  313.     g_Libraries.reserve(g_LibrariesNum);
  314.     for (size_t i = 0; i < g_LibrariesNum; i++)
  315.     {
  316.         int booksCount;
  317.         in >> booksCount;
  318.  
  319.         int signUpDays;
  320.         in >> signUpDays;
  321.  
  322.         int booksPerDay;
  323.         in >> booksPerDay;
  324.  
  325.         vector<int> books(booksCount);
  326.         for (int& bookId : books)
  327.             in >> bookId;
  328.  
  329.         g_Libraries.emplace_back(i, std::move(books), signUpDays, booksPerDay);
  330.     }
  331.  
  332.     in.close();
  333. }
  334. void DoOutput(const string& filename, const Scanner& scanner)
  335. {
  336.     ofstream out("test/" + filename + ".out", ios::out);
  337.     scanner.DoOutput(out);
  338.     out.close();
  339. }
  340.  
  341. double GetMedian()
  342. {
  343.     static double median = -1;
  344.     if (median < 0.0)
  345.     {
  346.         auto scores = g_Books.Scores;
  347.         std::sort(scores.begin(), scores.end());
  348.         const auto size = scores.size();
  349.         if (size % 2 == 0)
  350.         {
  351.             auto mid = size / 2;
  352.             median = ((double)(scores[mid] + scores[mid - 1])) / 2.0;
  353.         }
  354.         else
  355.         {
  356.             median = scores[size / 2];
  357.         }
  358.     }
  359.  
  360.     return median;
  361. }
  362.  
  363. long long GetTotalScore()
  364. {
  365.     static long long totalScore = -1;
  366.     if (totalScore < 0)
  367.     {
  368.         for (int i = 0; i < g_BooksNum; ++i)
  369.             totalScore += SCORE(i);
  370.     }
  371.  
  372.     return totalScore;
  373. }
  374.  
  375. #define USE_STATIC_SORT
  376. //#define USE_DYNAMIC_SHIT
  377. #if defined(USE_STATIC_SORT)
  378. double LibraryH(const Library& library)
  379. {
  380.     //return (library.TotalScore * library.SignUpTime) / library.BooksPerDay;
  381.     //return (((D - library.SignUpTime) * library.Books.size()) + library.BooksPerDay);
  382.     /*return ((double)library.TotalScore
  383.             * ((double)g_DaysNum - (double)library.BookIds.size() / (double)library.BooksPerDay + GetMedian()))
  384.         / (double)library.SignUpDays;*/
  385.  
  386.     double possibleScore = 0, libIndex = 0;
  387.  
  388.     for (int i = 0; i < (g_DaysNum - library.SignUpDays) && libIndex < library.BookIds.size(); ++i)
  389.     {
  390.         for (int j = 0; j < library.BooksPerDay && libIndex < library.BookIds.size(); ++j)
  391.         {
  392.             possibleScore += SCORE(library.BookIds[libIndex]);
  393.             ++libIndex;
  394.         }
  395.     }
  396.  
  397.     return (g_DaysNum - library.SignUpDays) * library.BooksPerDay * possibleScore;
  398.     //return ((possibleScore + GetMedian()) * (g_DaysNum - (library.BookIds.size()) / library.BooksPerDay)) / library.SignUpDays;
  399.     //return GetTotalScore()
  400.     //  - (g_BooksNum / library.BookIds.size()) + (possibleScore * (g_DaysNum - (library.BookIds.size()) / library.BooksPerDay)) / library.SignUpDays;
  401.     //
  402. }
  403.  
  404. int PickLibByStaticSort()
  405. {
  406.     static bool shouldSort = true;
  407.     static int nextIdx = 0;
  408.     static vector<int> libraryIds;
  409.  
  410.     if (shouldSort)
  411.     {
  412.         shouldSort = false;
  413.  
  414.         for (int i = 0; i < g_LibrariesNum; ++i)
  415.             libraryIds.push_back(i);
  416.  
  417.         //sort by heuristic
  418.         std::sort(libraryIds.begin(), libraryIds.end(),
  419.             [](int lhs, int rhs) {return LibraryH(LIBRARY(lhs)) > LibraryH(LIBRARY(rhs)); }
  420.         );
  421.     }
  422.  
  423.     return nextIdx < g_LibrariesNum ? libraryIds[nextIdx++] : -1;
  424. }
  425. #elif defined(USE_DYNAMIC_SHIT)
  426. /*Heuristic of a library, considering current scanning libraries and the current day*/
  427. double LibraryH(const Library& library, const Scanner& scanner, int today)
  428. {
  429.     //return library.Id;
  430.     static unordered_map<int, double> cachedResults;
  431.     static int lastRefreshedDay = -1;
  432.  
  433.     if (today > lastRefreshedDay)
  434.         cachedResults.clear();
  435.  
  436.     auto it = cachedResults.find(library.Id);
  437.     if (it != cachedResults.end())
  438.         return it->second;
  439.  
  440.     if (today + library.SignUpDays >= g_DaysNum)
  441.         return 0.0;
  442.  
  443.     double jointScore = 0.0, disjointScore = 0.0;
  444.     int jointCount = 0, disjointCount = 0;
  445.     for (int bookId : library.BookIds)
  446.     {
  447.         if (scanner.IsNewBook(bookId))
  448.         {
  449.             disjointScore += SCORE(bookId);
  450.             ++disjointCount;
  451.         }
  452.         else if (scanner.IsPendingBook(bookId))
  453.         {
  454.             jointScore += SCORE(bookId);
  455.             ++jointCount;
  456.         }
  457.     }
  458.  
  459.     //jointScore /= (double)jointCount;
  460.     //disjointScore /= (double)disjointCount;
  461.  
  462.     auto result = (double)library.BooksPerDay * (jointScore / (double)(library.SignUpDays*library.SignUpDays) + disjointScore / (double)library.SignUpDays);
  463.  
  464.     /*const double scansH = (scansMedian + scanner.GetScansAverageToday()) * 0.5 * (double)library.SignUpDays;
  465.     const double scansW = 0.3;
  466.     const double scansJointScoreEffect = 0.8;
  467.  
  468.     auto result = (double)library.BooksPerDay * (
  469.         (pow(scansJointScoreEffect, scansH * scansW)) * (jointScore / (double)jointCount)
  470.         + (disjointScore / (double)disjointCount)
  471.         );*/
  472.  
  473.     cachedResults[library.Id] = result;
  474.     return result;
  475. }
  476.  
  477. int PickLibByDynamicState(const Scanner& scanner, int today)
  478. {
  479.     static bool shouldInit = true;
  480.     static list<int> remainingLibIds;
  481.  
  482.     if (shouldInit)
  483.     {
  484.         shouldInit = false;
  485.         for (int i = 0; i < g_LibrariesNum; ++i)
  486.             remainingLibIds.push_back(i);
  487.     }
  488.  
  489.     if (remainingLibIds.empty())
  490.         return -1;
  491.  
  492.  
  493.  
  494.     auto optimalIt = std::max_element(remainingLibIds.begin(), remainingLibIds.end(),
  495.         [&](int lId, int rId)
  496.     {
  497.         return LibraryH(LIBRARY(lId), scanner, today) <
  498.             LibraryH(LIBRARY(rId), scanner, today);
  499.     }
  500.     );
  501.  
  502.     int result = *optimalIt;
  503.     remainingLibIds.erase(optimalIt);
  504.  
  505.     return result;
  506. }
  507. #endif
  508.  
  509.  
  510. int main()
  511. {
  512.     //input
  513.     string inputFile;
  514.     DoInput(inputFile);
  515.  
  516.     Scanner scanner;
  517.     int nextSignUpDay = 0;
  518.     int libId = -1;
  519.     //simulate days
  520.     bool shouldSignUp = true;
  521.     for (int day = 0; day < g_DaysNum; ++day)
  522.     {
  523.         if (day >= nextSignUpDay && libId != -1)
  524.         {
  525.             scanner.AddLibrary(libId);
  526.         }
  527.         if (shouldSignUp && day >= nextSignUpDay)
  528.         {
  529. #if defined(USE_STATIC_SORT)
  530.             libId = PickLibByStaticSort();
  531. #elif defined(USE_DYNAMIC_SHIT)
  532.             libId = PickLibByDynamicState(scanner, day);
  533. #endif
  534.             if (libId >= 0)
  535.             {
  536.                 nextSignUpDay += LIBRARY(libId).SignUpDays;
  537.             }
  538.             else
  539.             {
  540.                 shouldSignUp = false;
  541.             }
  542.         }
  543.  
  544.         scanner.ScanBooks();
  545.     }
  546.  
  547.     //output
  548.     DoOutput(inputFile, scanner);
  549.  
  550.     return 0;
  551. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement