제출 #601940

#제출 시각아이디문제언어결과실행 시간메모리
601940JeanBombeurBoarding Passes (BOI22_passes)C++17
55 / 100
605 ms12632 KiB
#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; // <|°_°|> // M. Broccoli const int MAX_GROUPS = (15); const int MAX_PASSENGERS = (1e5 + 1); const int LOG = 16; long long DP[1 << MAX_GROUPS]; vector <long long> Cost[MAX_GROUPS][MAX_GROUPS]; char Passengers[MAX_PASSENGERS]; vector <int> Seats[MAX_GROUPS]; int nbPassengers; void Read() { scanf("%s", Passengers); nbPassengers = strlen(Passengers); for (int i = 0; i < nbPassengers; i ++) { Seats[Passengers[i] - 'A'].push_back(i); } return; } long long NbLeft(int group, int seat) { int pos = -1; int sz = Seats[group].size(); for (int jump = 1 << LOG; jump; jump >>= 1) { if (pos + jump < sz && Seats[group][pos + jump] < seat) pos += jump; } return ++ pos; } long long NbRight(int group, int seat) { return Seats[group].size() - NbLeft(group, seat); } void Setup() { for (int set = 0; set < MAX_GROUPS; set ++) { for (int nouv = 0; nouv < MAX_GROUPS; nouv ++) { int sz = Seats[nouv].size(); long long sum = 0; for (int i = 0; i < sz; i ++) { sum += NbRight(set, Seats[nouv][i]); } Cost[set][nouv].push_back(sum); for (int cut = 0; cut < sz; cut ++) { sum += NbLeft(set, Seats[nouv][cut]) - NbRight(set, Seats[nouv][cut]); Cost[set][nouv].push_back(sum); } } } return; } bool GoLeft(int mask, int group, int cut) { int sz = Seats[group].size(); int cur = Seats[group][cut]; long long left = cut, right = sz - cut - 1; for (int i = 0; i < MAX_GROUPS; i ++) { if ((mask >> i) & 1) { left += 2 * NbLeft(i, cur); right += 2 * NbRight(i, cur); } } return left < right; } int FindCut(int mask, int group) { int cut = -1; int sz = Seats[group].size(); for (int jump = 1 << LOG; jump; jump >>= 1) { if (cut + jump < sz && GoLeft(mask, group, cut + jump)) cut += jump; } return ++ cut; } long long CostTransi(int mask, int group) { long long sum = 0; int sz = Seats[group].size(); int cut = FindCut(mask, group); for (int i = 0; i < MAX_GROUPS; i ++) { if ((mask >> i) & 1) sum += 2 * Cost[i][group][cut]; } sum += (cut * (cut - 1)) / 2 + ((sz - cut) * (sz - cut - 1)) / 2; return sum; } void Solve() { fill_n(DP, 1 << MAX_GROUPS, 1LL << 60); DP[0] = 0; for (int mask = 0; mask < (1 << MAX_GROUPS); mask ++) { for (int i = 0; i < MAX_GROUPS; i ++) { if (!((mask >> i) & 1)) DP[mask ^ (1 << i)] = min(DP[mask ^ (1 << i)], DP[mask] + CostTransi(mask, i)); } } printf("%lld", DP[(1 << MAX_GROUPS) - 1] / 2); if (DP[(1 << MAX_GROUPS) - 1] & 1) printf(".5"); printf("\n"); return; } int main() { Read(); Setup(); Solve(); return 0; }

컴파일 시 표준 에러 (stderr) 메시지

passes.cpp: In function 'void Read()':
passes.cpp:26:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   26 |     scanf("%s", Passengers);
      |     ~~~~~^~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...