Not easy but understandable solution c++ (beats 100% users)
Intuition\nwhen we see these type of problem with several possible choices one thing comes into our mind is the Dynamic Programming and here also one thing matt
# Intuition\nwhen we see these type of problem with several possible choices one thing comes into our mind is the Dynamic Programming and here also one thing matters the similarity in the type of the selection we got like we have to deal with the same type of the values from diffrent rows together and decide for a selection out of them all.\n\n# Approach\nWe will start with keeping all the elements of the 2 D array in a 1D array with the row marking and then to maximize the answer we will simply go by sorting and the once the sorting is done in descending order we will procide with DP initialization.\nafter initialization of the dp[0] = 0 and dp[1->2^n] = -Inf as we are dealing with sum in the 1D Dp and using mask which would take care of selection as for ex - 000,001,010,011,100,101,110,111 where one indicate the selection of a element from the row as (3rd_row)(2nd_row)(1st_row) as 111 represent the selection of 3 elements from 3 rows \n001 represents the selection of one element from first row and 100 represents the selection of one element from third row and so on.\n\n# Complexity\n- Time complexity:\n $$O((n\xD7mlog(n\xD7m))+O((n\xD7m)\xD72 \nn)$$ \n$$for__sorting :O(n\xD7mlog(n\xD7m))&&\n\n- Space complexity:\n\n\n# Code\n```cpp []\nclass Solution {\npublic:\n    int maxScore(vector<vector<int>>& grid) {\n        vector<int> vis(101,0);\n\n        int n = grid.size();\n        int m = grid[0].size();\n        \n       vector<pair<int,int>> elements;\n\n       for(int i = 0 ; i<n ; i++)\n       {\n            for(int j = 0 ; j<m ; j++)\n            {\n                elements.push_back({grid[i][j],i});\n            }\n       }\n\n       sort(elements.rbegin(),elements.rend());\n\n       vector<int> dp(1<<n,INT_MIN);\n       dp[0] = 0;\n\n       for(int i = 0 ; i<elements.size();)\n       {\n            int curr = elements[i].first;\n            vector<int> new_dp = dp;\n            int j = i ;\n\n            while(j<elements.size() && elements[j].first == curr ) j++;\n\n           for (int mask = 0; mask < (1 << n); ++mask) {\n                for (int k = i; k < j; ++k) {\n                    int value = elements[k].first;\n                    int row = elements[k].second;\n                    \n                    \n                    if (!(mask & (1 << row))) {\n                        new_dp[mask | (1 << row)] = max(new_dp[mask | (1 << row)], dp[mask] + value);\n                    }\n                }\n            }\n            dp = new_dp;\n            i = j;\n       }\n\n       int k  = *max_element(dp.begin(),dp.end());\n       return k;\n    }\n};\n```
['C++', 'Python3']