Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // #define INTERACTIVE
- #include <vector>
- #include <iostream>
- #include <chrono>
- #include <random>
- #include <deque>
- #include <set>
- #include <map>
- #include <iomanip>
- #include <fstream>
- #include <queue>
- #include <algorithm>
- using namespace std;
- typedef long long ll;
- typedef unsigned long long ull;
- typedef long double ld;
- typedef pair<int, int> pii;
- typedef pair<ll, ll> pll;
- typedef pair<double, double> pdd;
- //template <typename T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
- //template <typename T> using max_heap = priority_queue<T, vector<T>, less<T>>;
- template<typename A, typename B> ostream& operator<<(ostream& out, pair<A, B> p) { out << "(" << p.first << ", " << p.second << ")"; return out; }
- template<typename T> ostream& operator<<(ostream& out, vector<T> v) { out << "["; for (auto& x : v) out << x << ", "; out << "]"; return out; }
- template<typename T> ostream& operator<<(ostream& out, deque<T> v) { out << "["; for (auto& x : v) out << x << ", "; out << "]"; return out; }
- template<typename T> ostream& operator<<(ostream& out, set<T> v) { out << "{"; for (auto& x : v) out << x << ", "; out << "}"; return out; }
- template<typename K, typename V> ostream& operator<<(ostream& out, map<K, V> m) { out << "{"; for (auto& e : m) out << e.first << " -> " << e.second << ", "; out << "}"; return out; }
- template<typename T> T read() { T x; cin >> x; return x; }
- template<typename T> vector<T> read(int n) { vector<T> v(n); for (auto& x : v) cin >> x; return v; }
- template<typename A, typename B>istream& operator>>(istream& in, pair<A, B>& p) { return in >> p.first >> p.second; }
- #define FAST_IO ios_base::sync_with_stdio(false); cin.tie(nullptr)
- #define TESTS(t) int NUMBER_OF_TESTS; cin >> NUMBER_OF_TESTS; for(int t = 1; t <= NUMBER_OF_TESTS; t++)
- #define FOR(i, begin, end) for (int i = (begin); i < (end); i++)
- #define sgn(a) ((a) > eps ? 1 : ((a) < -eps ? -1 : 0))
- #define precise(x) fixed << setprecision(x)
- #define all(a) a.begin(), a.end()
- #define pb push_back
- #define rnd(a, b) (uniform_int_distribution<int>((a), (b))(rng))
- mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
- std::chrono::steady_clock::time_point __clock__;
- void startTime() { __clock__ = std::chrono::steady_clock::now(); }
- ld getTime() {
- auto end = std::chrono::steady_clock::now();
- auto t = std::chrono::duration_cast<std::chrono::microseconds> (end - __clock__).count();
- return ld(t) / 1e6;
- }
- void timeit(string msg) {
- cerr << "> " << msg << ": " << precise(6) << getTime() << endl;
- }
- template<typename T> inline bool maxi(T& a, T b) { return b > a ? (a = b, true) : false; }
- template<typename T> inline bool mini(T& a, T b) { return b < a ? (a = b, true) : false; }
- const ld PI = asin(1) * 2;
- const ld eps = 1e-6;
- const int oo = 2e9;
- const ll OO = 2e18;
- const ll MOD = 1000000007;
- const int MAXN = 200000;
- struct library {
- int id;
- int signupTime;
- int scansPerDay;
- vector<int> bookIds;
- };
- ostream& operator<<(ostream& out, const library& lib) {
- return out << "(t=" << lib.signupTime << ", m=" << lib.scansPerDay << ", bookIds=" << lib.bookIds << ")";
- }
- vector<int> bookValues;
- vector<library> libraries;
- int numDays;
- map<char, int> bestScores;
- void initScores() {
- bestScores['a'] = 21;
- bestScores['b'] = 5822900;
- bestScores['c'] = 5689822;
- bestScores['d'] = 5040490;
- bestScores['e'] = 5192117;
- bestScores['f'] = 5317473;
- }
- void reset() {
- bookValues.clear();
- libraries.clear();
- numDays = 0;
- }
- void readInput(string inFile) {
- ifstream in(inFile);
- int b, l;
- in >> b >> l >> numDays;
- bookValues.resize(b);
- for (auto& x : bookValues) in >> x;
- libraries.resize(l);
- int id = 0;
- for (auto& lib : libraries) {
- int n;
- lib.id = id;
- in >> n >> lib.signupTime >> lib.scansPerDay;
- lib.bookIds.resize(n);
- for (auto& i : lib.bookIds) {
- in >> i;
- }
- id++;
- }
- }
- queue<int> toQueue(vector<int> v) {
- queue<int> Q;
- for (auto x : v) Q.push(x);
- return Q;
- }
- int calcScore() {
- int score = 0;
- int timeLeft = numDays;
- vector<bool> isTaken(bookValues.size());
- for (auto& lib : libraries) {
- timeLeft -= lib.signupTime;
- if (timeLeft <= 0) break;
- int bookLimit = timeLeft * lib.scansPerDay;
- for (auto& bookId : lib.bookIds) {
- if (bookLimit-- == 0) break;
- isTaken[bookId] = true;
- }
- }
- FOR(i, 0, (int)bookValues.size()) {
- if (isTaken[i]) score += bookValues[i];
- }
- return score;
- }
- void dumpOutput(string problemId) {
- ofstream out("output_" + problemId + ".txt");
- out << libraries.size() << endl;
- for (auto& lib : libraries) {
- out << lib.id << " " << lib.bookIds.size() << endl;
- for (auto book : lib.bookIds) {
- out << book << " ";
- }
- out << endl;
- }
- }
- namespace sortBySignup {
- bool cmpLib(const library& a, const library& b) {
- return a.signupTime < b.signupTime;
- }
- void optimize() {
- sort(libraries.begin(), libraries.end(), cmpLib);
- cerr << "sorted by signup time" << endl;
- }
- }
- namespace sortByValuePerTime {
- vector<int> libValue;
- vector<vector<int>> parentLib;
- vector<int> bookVal;
- library pickLib() {
- int bestIndex = -1;
- double bestScore = -1;
- for (int i = 0; i < (int)libraries.size(); i++) {
- if (libValue[libraries[i].id] < 0)
- continue;
- double score = (double)libValue[libraries[i].id] / (double)libraries[i].signupTime;
- if (score > bestScore) {
- bestScore = score;
- bestIndex = i;
- }
- }
- auto lib = libraries[bestIndex];
- libValue[lib.id] = -1;
- return lib;
- }
- void optimize() {
- bookVal = bookValues;
- libValue.resize(0);
- libValue.resize(libraries.size());
- parentLib.clear();
- parentLib.resize(bookValues.size());
- for (auto& lib : libraries) {
- int total = 0;
- for (auto book : lib.bookIds) {
- total += bookVal[book];
- parentLib[book].push_back(lib.id);
- }
- libValue[lib.id] = total;
- }
- vector<library> newOrder;
- for (int i = 0; i < (int)libraries.size(); i++) {
- auto lib = pickLib();
- for (auto book : lib.bookIds) {
- if (bookVal[book] == -1)
- continue;
- auto val = bookVal[book];
- bookVal[book] = -1;
- for (auto pl : parentLib[book]) {
- libValue[pl] -= val;
- }
- }
- newOrder.push_back(lib);
- }
- libraries = newOrder;
- cerr << "sorted by value per time" << endl;
- }
- }
- namespace sortBooksByValue {
- bool cmpBook(const int& a, const int& b) {
- return bookValues[a] > bookValues[b];
- }
- void optimize() {
- for (auto& lib : libraries) {
- sort(lib.bookIds.begin(), lib.bookIds.end(), cmpBook);
- }
- cerr << "sorted books by value" << endl;
- }
- }
- namespace simulateAndSkipBooks {
- void optimize() {
- set<int> usedBookIds;
- int currentLib = 0;
- int queueTimeLeft = 0;
- vector<queue<int>> queues(libraries.size());
- vector<vector<int>> takenBooks(libraries.size());
- vector<vector<int>> skippedBooks(libraries.size());
- for (int day = 0; day < numDays; day++, queueTimeLeft--) {
- if (queueTimeLeft <= 0 && currentLib + 1 < (int)libraries.size()) {
- // enqueue new
- queues[currentLib] = toQueue(libraries[currentLib].bookIds);
- queueTimeLeft = libraries[currentLib].signupTime;
- currentLib++;
- }
- // process queues
- for (int i = (int)queues.size() - 1; i >= 0; i--) {
- // FOR(i, 0, (int)queues.size()) {
- auto& lib = libraries[i];
- FOR(_, 0, lib.scansPerDay) {
- if (queues[i].empty()) break;
- int bookId = queues[i].front(); queues[i].pop();
- if (usedBookIds.count(bookId) > 0) {
- // somehow skip this biatch
- skippedBooks[i].pb(bookId);
- _--;
- } else {
- takenBooks[i].pb(bookId);
- usedBookIds.insert(bookId);
- }
- }
- }
- }
- FOR(i, currentLib, (int)libraries.size()) {
- queues[i] = toQueue(libraries[i].bookIds);
- }
- FOR(i, 0, (int)queues.size()) {
- while (!queues[i].empty()) {
- skippedBooks[i].pb(queues[i].front());
- queues[i].pop();
- }
- }
- vector<library> newLibs;
- FOR(i, 0, (int)libraries.size()) {
- library l;
- l.id = libraries[i].id;
- l.scansPerDay = libraries[i].scansPerDay;
- l.signupTime = libraries[i].signupTime;
- for (auto x : takenBooks[i]) l.bookIds.pb(x);
- for (auto x : skippedBooks[i]) l.bookIds.pb(x);
- if (l.bookIds.size() > 0) newLibs.pb(l);
- }
- libraries = newLibs;
- }
- }
- namespace sortByValuePerTime2 {
- vector<bool> isTaken;
- library pickLibrary(int timeLeft) {
- int bestIndex = 0;
- double bestScore = -1;
- for (int i = 0; i < libraries.size(); i++) {
- if (libraries[i].signupTime >= timeLeft)
- continue;
- int bookLimit = timeLeft * libraries[i].scansPerDay;
- int libScore = 0;
- for (auto book : libraries[i].bookIds) {
- if (isTaken[book])
- continue;
- libScore += bookValues[book];
- bookLimit -= 1;
- if (bookLimit <= 0)
- break;
- }
- double score = (double)libScore / (double)libraries[i].signupTime;
- if (score > bestScore) {
- bestIndex = i;
- bestScore = score;
- }
- }
- auto x = libraries[bestIndex];
- libraries[bestIndex] = libraries[libraries.size() - 1];
- libraries.pop_back();
- return x;
- }
- void optimize() {
- isTaken.clear();
- isTaken.resize(bookValues.size());
- vector<library> newOrder;
- int timeLeft = numDays;
- while (libraries.size() > 0) {
- auto lib = pickLibrary(timeLeft);
- timeLeft -= lib.signupTime;
- newOrder.push_back(lib);
- int bookLimit = timeLeft * lib.scansPerDay;
- for (auto book : lib.bookIds) {
- if (isTaken[book])
- continue;
- isTaken[book] = true;
- bookLimit--;
- if (bookLimit <= 0)
- break;
- }
- }
- libraries = newOrder;
- cerr << "sorted by value per time (2)" << endl;
- }
- }
- namespace sortBooksBySomethingArbitrary {
- vector<bool> isTaken;
- vector<bool> isLibraryComplete;
- void optimize() {
- isTaken.clear();
- isTaken.resize(bookValues.size());
- isLibraryComplete.clear();
- isLibraryComplete.resize(libraries.size());
- while (true) {
- bool completedAny = false;
- int timeLeft = numDays;
- for (int i = 0; i < libraries.size(); i++) {
- timeLeft -= libraries[i].signupTime;
- if (isLibraryComplete[i])
- continue;
- int booksTaken = 0;
- for (auto book : libraries[i].bookIds)
- if (!isTaken[book])
- booksTaken++;
- if (booksTaken <= timeLeft * libraries[i].scansPerDay) {
- isLibraryComplete[i] = true;
- for (auto book : libraries[i].bookIds)
- isTaken[book] = true;
- completedAny = true;
- }
- }
- if (!completedAny)
- break;
- }
- int timeLeft = numDays;
- for (int i = 0; i < libraries.size(); i++) {
- timeLeft -= libraries[i].signupTime;
- if (isLibraryComplete[i])
- continue;
- vector<int> take;
- vector<int> notTake;
- int bookLimit = timeLeft * libraries[i].scansPerDay;
- for (auto book : libraries[i].bookIds) {
- if (bookLimit <= 0 || isTaken[book]) {
- notTake.push_back(book);
- } else {
- isTaken[book] = true;
- take.push_back(book);
- bookLimit--;
- }
- }
- libraries[i].bookIds.clear();
- for (auto x : take) libraries[i].bookIds.push_back(x);
- for (auto x : notTake) libraries[i].bookIds.push_back(x);
- }
- cerr << "finished sorting books by something arbitrary" << endl;
- }
- }
- namespace tryToFixLastLibrary {
- void optimize(string problemId, int requiredDiff) {
- int score = calcScore();
- int bestScore = bestScores[problemId[0]];
- cout << "currently behind " << score - bestScore << endl;
- int steps = libraries.size() * (libraries.size() - 1) / 2;
- FOR(i, 0, (int)libraries.size()) {
- FOR(j, i + 1, (int)libraries.size()) {
- steps--;
- if (steps % 20000 == 0) {
- cout << "steps remaining: " << steps << endl;
- }
- swap(libraries[i], libraries[j]);
- int newScore = calcScore();
- if (newScore > score + requiredDiff) {
- cout << "got extra " << newScore - score << endl;
- score = newScore;
- cout << "still behind " << bestScore - score << endl;
- if (score > bestScore) dumpOutput(problemId);
- } else {
- swap(libraries[i], libraries[j]);
- }
- }
- }
- // if (bestI != -1 && bestJ != -1) {
- // swap(libraries[bestI], libraries[bestJ]);
- // }
- }
- }
- namespace sortLibrariesWell {
- vector<bool> isTaken;
- vector<int> bookRep;
- library pickLibrary(int timeLeft) {
- int bestIndex = 0;
- double bestScore = -1;
- for (int i = 0; i < libraries.size(); i++) {
- if (libraries[i].signupTime >= timeLeft)
- continue;
- int bookLimit = timeLeft * libraries[i].scansPerDay;
- double libScore = 0;
- for (auto book : libraries[i].bookIds) {
- if (isTaken[book])
- continue;
- libScore += bookValues[book] / sqrt(sqrt((double)bookRep[book]));
- bookLimit -= 1;
- if (bookLimit <= 0)
- break;
- }
- double score = (double)libScore / (double)libraries[i].signupTime;
- if (score > bestScore) {
- bestIndex = i;
- bestScore = score;
- }
- }
- auto x = libraries[bestIndex];
- libraries[bestIndex] = libraries[libraries.size() - 1];
- libraries.pop_back();
- return x;
- }
- void optimize() {
- isTaken.clear();
- isTaken.resize(bookValues.size());
- bookRep.clear();
- bookRep.resize(bookValues.size());
- for (auto& lib : libraries) {
- for (auto book : lib.bookIds) {
- bookRep[book]++;
- }
- }
- vector<library> newOrder;
- int timeLeft = numDays;
- while (libraries.size() > 0) {
- auto lib = pickLibrary(timeLeft);
- timeLeft -= lib.signupTime;
- newOrder.push_back(lib);
- int bookLimit = timeLeft * lib.scansPerDay;
- for (auto book : lib.bookIds) {
- if (isTaken[book])
- continue;
- bookRep[book] -= 1;
- isTaken[book] = true;
- bookLimit--;
- if (bookLimit <= 0)
- break;
- }
- }
- libraries = newOrder;
- cerr << "sorted libraries well" << endl;
- }
- }
- void solve(string problemId) {
- initScores();
- readInput("inputs/" + problemId + ".txt");
- sortByValuePerTime::optimize();
- //sortBySignup::optimize();
- sortBooksByValue::optimize();
- if (problemId[0] == 'd' || problemId[0] == 'e') {
- sortLibrariesWell::optimize();
- } else {
- sortByValuePerTime2::optimize();
- }
- simulateAndSkipBooks::optimize();
- sortBooksBySomethingArbitrary::optimize();
- tryToFixLastLibrary::optimize(problemId, 100);
- simulateAndSkipBooks::optimize();
- tryToFixLastLibrary::optimize(problemId, 0);
- for (;;) {
- simulateAndSkipBooks::optimize();
- tryToFixLastLibrary::optimize(problemId, 0);
- }
- cout << "\t\t\t\t\t" << problemId[0] << " score: " << calcScore() << " (diff: " << calcScore() - bestScores[problemId[0]] << ")" << endl;
- if (calcScore() > bestScores[problemId[0]]) {
- cout << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmazing" << endl;
- }
- dumpOutput(problemId);
- cerr << "finished " << problemId << endl;
- }
- int main() {
- FAST_IO;
- startTime();
- // solve("a_example");
- // solve("b_read_on");
- //solve("c_incunabula");
- // solve("d_tough_choices");
- solve("e_so_many_books");
- //solve("f_libraries_of_the_world");
- timeit("Finished");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement