- Define precisely what one DP state represents.
- Establish the base cases before transitions are evaluated.
- Process states in dependency order and combine only already-known values.
Code notes
- 192 lines of C++ from the credited upstream file minimum-possible-maximum-waiting-time.cpp.
- The implementation visibly relies on sequence storage, cached states.
- 12 loop blocks detected.
Complexity
Multiply the number of reachable states by the work performed for each transition, then include the stored state table in memory usage.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class Solution {6public:7 int minMaxWaitingTime(vector<int>& demand, vector<int>& fuel) {8 const auto& binary_search = [](int left, int right, const auto& check) {9 while (left <= right) {10 const auto& mid = left + (right - left) / 2;11 if (check(mid)) {12 right = mid - 1;13 } else {14 left = mid + 1;15 }16 }17 return left;18 };19 20 const auto& low = [](int x) -> uint64_t {21 return x >= 63 ? ~uint64_t{0} : x >= 0 ? ((uint64_t{1} << (x + 1)) - 1) : 0;22 };23 24 const auto& high = [&](int x) -> uint64_t {25 return ~uint64_t{0} ^ low(x - 1);26 };27 28 const auto& find_max_served = [&]() -> int {29 uint64_t mask = 1;30 for (int i = 0, total = 0; i < size(demand); ++i) {31 mask = ((mask << demand[i]) & low(fuel[0])) | (mask & high(total + demand[i] - fuel[1]));32 if (!mask) {33 return i;34 }35 total += demand[i];36 }37 return size(demand);38 };39 40 const auto& l = find_max_served();41 if (!l) {42 return -1;43 }44 45 const auto& mx = ranges::max(demand);46 const auto& check = [&](int w) {47 48 49 50 51 vector<vector<uint64_t>> dp(2, vector<uint64_t>(mx + 1));52 dp[0][0] = 1;53 for (int i = 0, total = 0; i < l; ++i) {54 vector<vector<uint64_t>> new_dp(2, vector<uint64_t>(mx + 1));55 const auto& update = [&](int last, int gap, uint64_t mask) {56 if (last == 0) {57 mask = (mask << demand[i]) & low(fuel[0]);58 } else {59 mask &= high(total + demand[i] - fuel[1]);60 }61 new_dp[last][gap] |= mask;62 };63 64 for (int last = 0; last < size(dp); ++last) {65 for (int gap = 0; gap < size(dp[0]); ++gap) {66 if (!dp[last][gap]) {67 continue;68 }69 if ((i - 1 >= 0 ? demand[i - 1] : 0) <= w) {70 update(last, max(gap - (i - 1 >= 0 ? demand[i - 1] : 0), 0), dp[last][gap]);71 }72 if (gap <= w) {73 update(last ^ 1, max((i - 1 >= 0 ? demand[i - 1] : 0) - gap, 0), dp[last][gap]);74 }75 }76 }77 dp = move(new_dp);78 total += demand[i];79 }80 return ranges::any_of(dp, [](const auto& row) {81 return ranges::any_of(row, [](uint64_t mask) {82 return mask != 0;83 });84 });85 };86 87 return binary_search(0, mx, check);88 }89};90 91929394class Solution2 {95public:96 int minMaxWaitingTime(vector<int>& demand, vector<int>& fuel) {97 const auto& binary_search = [](int left, int right, const auto& check) {98 while (left <= right) {99 const auto& mid = left + (right - left) / 2;100 if (check(mid)) {101 right = mid - 1;102 } else {103 left = mid + 1;104 }105 }106 return left;107 };108 109 const auto& find_max_served = [&]() -> int {110 111 vector<bool> dp(fuel[0] + 1);112 dp[0] = true;113 for (int i = 0, total = 0; i < size(demand); ++i) {114 vector<bool> new_dp(fuel[0] + 1);115 for (int used0 = 0; used0 <= fuel[0]; ++used0) {116 if (!dp[used0]) {117 continue;118 }119 if (used0 + demand[i] <= fuel[0]) {120 new_dp[used0 + demand[i]] = true;121 }122 if (total - used0 + demand[i] <= fuel[1]) {123 new_dp[used0] = true;124 }125 }126 if (!ranges::any_of(new_dp, [](bool ok) { return ok; })) {127 return i;128 }129 dp = move(new_dp);130 total += demand[i];131 }132 return size(demand);133 };134 135 const auto& l = find_max_served();136 if (!l) {137 return -1;138 }139 140 const auto& mx = ranges::max(demand);141 const auto& check = [&](int w) {142 143 144 145 146 vector<vector<vector<bool>>> dp(2, vector<vector<bool>>(mx + 1, vector<bool>(fuel[0] + 1)));147 dp[0][0][0] = true;148 for (int i = 0, total = 0; i < l; ++i) {149 vector<vector<vector<bool>>> new_dp(2, vector<vector<bool>>(mx + 1, vector<bool>(fuel[0] + 1)));150 const auto& update = [&](int last, int gap, int used0) {151 if (last == 0) {152 if (used0 + demand[i] <= fuel[0]) {153 new_dp[last][gap][used0 + demand[i]] = true;154 }155 } else {156 if (total - used0 + demand[i] <= fuel[1]) {157 new_dp[last][gap][used0] = true;158 }159 }160 };161 162 for (int last = 0; last < size(dp); ++last) {163 for (int gap = 0; gap < size(dp[0]); ++gap) {164 for (int used0 = 0; used0 < size(dp[0][0]); ++used0) {165 if (!dp[last][gap][used0]) {166 continue;167 }168 if ((i - 1 >= 0 ? demand[i - 1] : 0) <= w) {169 update(last, max(gap - (i - 1 >= 0 ? demand[i - 1] : 0), 0), used0);170 }171 if (gap <= w) {172 update(last ^ 1, max((i - 1 >= 0 ? demand[i - 1] : 0) - gap, 0), used0);173 }174 }175 }176 }177 dp = move(new_dp);178 total += demand[i];179 }180 return ranges::any_of(dp, [](const auto& matrix) {181 return ranges::any_of(matrix, [](const auto& row) {182 return ranges::any_of(row, [](bool x) {183 return x;184 });185 });186 });187 };188 189 return binary_search(0, mx, check);190 }191};192