/*
Problem: Maximum Minimum Rating
Company Tag: D. E. Shaw OA
Problem Statement:
We are given a 2D array rating of size n x m.
There are n customers and m products.
rating[i][j] means the rating given by customer i to product j.
We need to select exactly n - 2 products.
After selecting products, for every customer i:
mx[i] = maximum rating customer i gave among selected products
Then we take:
minimum value among all mx[i]
Our task is to maximize this minimum value.
Constraints:
2 <= n <= 100
n <= m <= 100
1 <= rating[i][j] <= 100
Brute Force:
Try every possible set of n - 2 products.
For each set, calculate the answer.
Why Brute Force Fails:
m can be 100, so choosing all possible product sets is too expensive.
Optimized Idea:
I check whether a value x can be achieved.
For x to be possible:
Every customer must have at least one selected product
with rating >= x.
If each customer needs a separate product, we may need n products.
But we can choose only n - 2 products.
So we need to save 2 selections.
This can happen if:
1. One product satisfies at least 3 customers.
2. Two products together satisfy at least 4 customers.
Explanation Block:
I convert every product into a set of customers it can satisfy for value x.
Then:
- If any customer is not satisfied by any product, x is impossible.
- If one product satisfies 3 customers, we save 2 products.
- If two products together satisfy 4 customers, we save 2 products.
Since rating values are from 1 to 100, I simply try every x.
Dry Run:
rating =
[
[3, 4, 2, 2],
[3, 3, 3, 4],
[2, 4, 2, 3],
[4, 2, 4, 2]
]
For x = 3:
Product 0 satisfies customers 0, 1, and 3.
One product satisfies 3 customers.
So x = 3 is possible.
Answer = 3
Time Complexity:
O(100 * m * m)
Space Complexity:
O(m * n)
*/
#include <bits/stdc++.h>
using namespace std;
bool canMake(vector<vector<int>>& rating, int x) {
int n = rating.size();
int m = rating[0].size();
int productsToPick = n - 2;
// If we cannot pick any product, then this checking is not meaningful.
if (productsToPick <= 0) {
return false;
}
vector<bitset<105>> good(m);
// good[j][i] = 1 means product j can satisfy customer i for value x.
for (int i = 0; i < n; i++) {
bool hasGoodProduct = false;
for (int j = 0; j < m; j++) {
if (rating[i][j] >= x) {
good[j].set(i);
hasGoodProduct = true;
}
}
// If any customer has no product with rating >= x,
// then x cannot be achieved.
if (!hasGoodProduct) {
return false;
}
}
// Case 1:
// One product satisfies at least 3 customers.
// Instead of choosing 3 separate products, I choose only 1.
// So I save 2 selections.
for (int j = 0; j < m; j++) {
if ((int)good[j].count() >= 3) {
return true;
}
}
// Case 2:
// Two products together satisfy at least 4 customers.
// Instead of choosing 4 separate products, I choose only 2.
// Again, I save 2 selections.
for (int a = 0; a < m; a++) {
for (int b = a + 1; b < m; b++) {
bitset<105> combined = good[a] | good[b];
if ((int)combined.count() >= 4) {
return true;
}
}
}
return false;
}
int getMaximumRating(vector<vector<int>>& rating) {
int ans = 0;
// Since rating values are only from 1 to 100,
// I try every possible answer.
for (int x = 1; x <= 100; x++) {
if (canMake(rating, x)) {
ans = x;
}
}
return ans;
}
int main() {
vector<vector<int>> rating = {
{3, 4, 2, 2},
{3, 3, 3, 4},
{2, 4, 2, 3},
{4, 2, 4, 2}
};
cout << getMaximumRating(rating) << endl;
return 0;
}
LyoKICAgIFByb2JsZW06IE1heGltdW0gTWluaW11bSBSYXRpbmcKICAgIENvbXBhbnkgVGFnOiBELiBFLiBTaGF3IE9BCgogICAgUHJvYmxlbSBTdGF0ZW1lbnQ6CiAgICAgICAgV2UgYXJlIGdpdmVuIGEgMkQgYXJyYXkgcmF0aW5nIG9mIHNpemUgbiB4IG0uCgogICAgICAgIFRoZXJlIGFyZSBuIGN1c3RvbWVycyBhbmQgbSBwcm9kdWN0cy4KICAgICAgICByYXRpbmdbaV1bal0gbWVhbnMgdGhlIHJhdGluZyBnaXZlbiBieSBjdXN0b21lciBpIHRvIHByb2R1Y3Qgai4KCiAgICAgICAgV2UgbmVlZCB0byBzZWxlY3QgZXhhY3RseSBuIC0gMiBwcm9kdWN0cy4KCiAgICAgICAgQWZ0ZXIgc2VsZWN0aW5nIHByb2R1Y3RzLCBmb3IgZXZlcnkgY3VzdG9tZXIgaToKICAgICAgICAgICAgbXhbaV0gPSBtYXhpbXVtIHJhdGluZyBjdXN0b21lciBpIGdhdmUgYW1vbmcgc2VsZWN0ZWQgcHJvZHVjdHMKCiAgICAgICAgVGhlbiB3ZSB0YWtlOgogICAgICAgICAgICBtaW5pbXVtIHZhbHVlIGFtb25nIGFsbCBteFtpXQoKICAgICAgICBPdXIgdGFzayBpcyB0byBtYXhpbWl6ZSB0aGlzIG1pbmltdW0gdmFsdWUuCgogICAgQ29uc3RyYWludHM6CiAgICAgICAgMiA8PSBuIDw9IDEwMAogICAgICAgIG4gPD0gbSA8PSAxMDAKICAgICAgICAxIDw9IHJhdGluZ1tpXVtqXSA8PSAxMDAKCiAgICBCcnV0ZSBGb3JjZToKICAgICAgICBUcnkgZXZlcnkgcG9zc2libGUgc2V0IG9mIG4gLSAyIHByb2R1Y3RzLgogICAgICAgIEZvciBlYWNoIHNldCwgY2FsY3VsYXRlIHRoZSBhbnN3ZXIuCgogICAgV2h5IEJydXRlIEZvcmNlIEZhaWxzOgogICAgICAgIG0gY2FuIGJlIDEwMCwgc28gY2hvb3NpbmcgYWxsIHBvc3NpYmxlIHByb2R1Y3Qgc2V0cyBpcyB0b28gZXhwZW5zaXZlLgoKICAgIE9wdGltaXplZCBJZGVhOgogICAgICAgIEkgY2hlY2sgd2hldGhlciBhIHZhbHVlIHggY2FuIGJlIGFjaGlldmVkLgoKICAgICAgICBGb3IgeCB0byBiZSBwb3NzaWJsZToKICAgICAgICAgICAgRXZlcnkgY3VzdG9tZXIgbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBzZWxlY3RlZCBwcm9kdWN0CiAgICAgICAgICAgIHdpdGggcmF0aW5nID49IHguCgogICAgICAgIElmIGVhY2ggY3VzdG9tZXIgbmVlZHMgYSBzZXBhcmF0ZSBwcm9kdWN0LCB3ZSBtYXkgbmVlZCBuIHByb2R1Y3RzLgogICAgICAgIEJ1dCB3ZSBjYW4gY2hvb3NlIG9ubHkgbiAtIDIgcHJvZHVjdHMuCgogICAgICAgIFNvIHdlIG5lZWQgdG8gc2F2ZSAyIHNlbGVjdGlvbnMuCgogICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZjoKICAgICAgICAgICAgMS4gT25lIHByb2R1Y3Qgc2F0aXNmaWVzIGF0IGxlYXN0IDMgY3VzdG9tZXJzLgogICAgICAgICAgICAyLiBUd28gcHJvZHVjdHMgdG9nZXRoZXIgc2F0aXNmeSBhdCBsZWFzdCA0IGN1c3RvbWVycy4KCiAgICBFeHBsYW5hdGlvbiBCbG9jazoKICAgICAgICBJIGNvbnZlcnQgZXZlcnkgcHJvZHVjdCBpbnRvIGEgc2V0IG9mIGN1c3RvbWVycyBpdCBjYW4gc2F0aXNmeSBmb3IgdmFsdWUgeC4KCiAgICAgICAgVGhlbjoKICAgICAgICAgICAgLSBJZiBhbnkgY3VzdG9tZXIgaXMgbm90IHNhdGlzZmllZCBieSBhbnkgcHJvZHVjdCwgeCBpcyBpbXBvc3NpYmxlLgogICAgICAgICAgICAtIElmIG9uZSBwcm9kdWN0IHNhdGlzZmllcyAzIGN1c3RvbWVycywgd2Ugc2F2ZSAyIHByb2R1Y3RzLgogICAgICAgICAgICAtIElmIHR3byBwcm9kdWN0cyB0b2dldGhlciBzYXRpc2Z5IDQgY3VzdG9tZXJzLCB3ZSBzYXZlIDIgcHJvZHVjdHMuCgogICAgICAgIFNpbmNlIHJhdGluZyB2YWx1ZXMgYXJlIGZyb20gMSB0byAxMDAsIEkgc2ltcGx5IHRyeSBldmVyeSB4LgoKICAgIERyeSBSdW46CiAgICAgICAgcmF0aW5nID0KICAgICAgICBbCiAgICAgICAgICAgIFszLCA0LCAyLCAyXSwKICAgICAgICAgICAgWzMsIDMsIDMsIDRdLAogICAgICAgICAgICBbMiwgNCwgMiwgM10sCiAgICAgICAgICAgIFs0LCAyLCA0LCAyXQogICAgICAgIF0KCiAgICAgICAgRm9yIHggPSAzOgogICAgICAgICAgICBQcm9kdWN0IDAgc2F0aXNmaWVzIGN1c3RvbWVycyAwLCAxLCBhbmQgMy4KCiAgICAgICAgT25lIHByb2R1Y3Qgc2F0aXNmaWVzIDMgY3VzdG9tZXJzLgogICAgICAgIFNvIHggPSAzIGlzIHBvc3NpYmxlLgoKICAgICAgICBBbnN3ZXIgPSAzCgogICAgVGltZSBDb21wbGV4aXR5OgogICAgICAgIE8oMTAwICogbSAqIG0pCgogICAgU3BhY2UgQ29tcGxleGl0eToKICAgICAgICBPKG0gKiBuKQoqLwoKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpib29sIGNhbk1ha2UodmVjdG9yPHZlY3RvcjxpbnQ+PiYgcmF0aW5nLCBpbnQgeCkgewogICAgaW50IG4gPSByYXRpbmcuc2l6ZSgpOwogICAgaW50IG0gPSByYXRpbmdbMF0uc2l6ZSgpOwoKICAgIGludCBwcm9kdWN0c1RvUGljayA9IG4gLSAyOwoKICAgIC8vIElmIHdlIGNhbm5vdCBwaWNrIGFueSBwcm9kdWN0LCB0aGVuIHRoaXMgY2hlY2tpbmcgaXMgbm90IG1lYW5pbmdmdWwuCiAgICBpZiAocHJvZHVjdHNUb1BpY2sgPD0gMCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICB2ZWN0b3I8Yml0c2V0PDEwNT4+IGdvb2QobSk7CgogICAgLy8gZ29vZFtqXVtpXSA9IDEgbWVhbnMgcHJvZHVjdCBqIGNhbiBzYXRpc2Z5IGN1c3RvbWVyIGkgZm9yIHZhbHVlIHguCiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGJvb2wgaGFzR29vZFByb2R1Y3QgPSBmYWxzZTsKCiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBtOyBqKyspIHsKICAgICAgICAgICAgaWYgKHJhdGluZ1tpXVtqXSA+PSB4KSB7CiAgICAgICAgICAgICAgICBnb29kW2pdLnNldChpKTsKICAgICAgICAgICAgICAgIGhhc0dvb2RQcm9kdWN0ID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gSWYgYW55IGN1c3RvbWVyIGhhcyBubyBwcm9kdWN0IHdpdGggcmF0aW5nID49IHgsCiAgICAgICAgLy8gdGhlbiB4IGNhbm5vdCBiZSBhY2hpZXZlZC4KICAgICAgICBpZiAoIWhhc0dvb2RQcm9kdWN0KSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICB9CgogICAgLy8gQ2FzZSAxOgogICAgLy8gT25lIHByb2R1Y3Qgc2F0aXNmaWVzIGF0IGxlYXN0IDMgY3VzdG9tZXJzLgogICAgLy8gSW5zdGVhZCBvZiBjaG9vc2luZyAzIHNlcGFyYXRlIHByb2R1Y3RzLCBJIGNob29zZSBvbmx5IDEuCiAgICAvLyBTbyBJIHNhdmUgMiBzZWxlY3Rpb25zLgogICAgZm9yIChpbnQgaiA9IDA7IGogPCBtOyBqKyspIHsKICAgICAgICBpZiAoKGludClnb29kW2pdLmNvdW50KCkgPj0gMykgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgLy8gQ2FzZSAyOgogICAgLy8gVHdvIHByb2R1Y3RzIHRvZ2V0aGVyIHNhdGlzZnkgYXQgbGVhc3QgNCBjdXN0b21lcnMuCiAgICAvLyBJbnN0ZWFkIG9mIGNob29zaW5nIDQgc2VwYXJhdGUgcHJvZHVjdHMsIEkgY2hvb3NlIG9ubHkgMi4KICAgIC8vIEFnYWluLCBJIHNhdmUgMiBzZWxlY3Rpb25zLgogICAgZm9yIChpbnQgYSA9IDA7IGEgPCBtOyBhKyspIHsKICAgICAgICBmb3IgKGludCBiID0gYSArIDE7IGIgPCBtOyBiKyspIHsKICAgICAgICAgICAgYml0c2V0PDEwNT4gY29tYmluZWQgPSBnb29kW2FdIHwgZ29vZFtiXTsKCiAgICAgICAgICAgIGlmICgoaW50KWNvbWJpbmVkLmNvdW50KCkgPj0gNCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwp9CgppbnQgZ2V0TWF4aW11bVJhdGluZyh2ZWN0b3I8dmVjdG9yPGludD4+JiByYXRpbmcpIHsKICAgIGludCBhbnMgPSAwOwoKICAgIC8vIFNpbmNlIHJhdGluZyB2YWx1ZXMgYXJlIG9ubHkgZnJvbSAxIHRvIDEwMCwKICAgIC8vIEkgdHJ5IGV2ZXJ5IHBvc3NpYmxlIGFuc3dlci4KICAgIGZvciAoaW50IHggPSAxOyB4IDw9IDEwMDsgeCsrKSB7CiAgICAgICAgaWYgKGNhbk1ha2UocmF0aW5nLCB4KSkgewogICAgICAgICAgICBhbnMgPSB4OwogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gYW5zOwp9CgppbnQgbWFpbigpIHsKICAgIHZlY3Rvcjx2ZWN0b3I8aW50Pj4gcmF0aW5nID0gewogICAgICAgIHszLCA0LCAyLCAyfSwKICAgICAgICB7MywgMywgMywgNH0sCiAgICAgICAgezIsIDQsIDIsIDN9LAogICAgICAgIHs0LCAyLCA0LCAyfQogICAgfTsKCiAgICBjb3V0IDw8IGdldE1heGltdW1SYXRpbmcocmF0aW5nKSA8PCBlbmRsOwoKICAgIHJldHVybiAwOwp9