SRM516 Div1 Medium(500) RowsOrdering
Example 0の{"bb", "cb", "ca"}は、1番目cb、2番目bb、51番目caと並べるのが最善。これを、1列目によってcbの順位が+0、bbの順位が+1、caの順位が+0され、2列目によってcbの順位が+0, bbの順位が+0、caの順位が+50されると考える。そうすると、それぞれの列について分けて考えることができる。
各列では多く出現する文字を前にするのが最善。
ある列iを最後に選ぶ場合の順位への寄与の和(下のプログラムでのcont[i])をxとすると、列iをk番目に選んだときの順位への寄与は50M-kx。列は順位への寄与の大きい順位に選んでいくのが最善。
#include <string> #include <vector> #include <algorithm> using namespace std; class RowsOrdering{public: int order( vector <string> rows ) { long long mod = 1000000007; int n = (int)rows.size(); int M = (int)rows[0].size(); vector<int> cont(M); for ( int i=0; i<M; i++ ) { int c[256] = {0}; for ( int j=0; j<n; j++ ) c[(int)rows[j][i]]++; sort(c,c+256); cont[i] = 0; for ( int j=0; j<n; j++ ) cont[i] += c[255-j]*j; } sort( cont.begin(), cont.end() ); long long ans = 0; long long p = 1; for ( int i=0; i<M; i++ ) { ans += cont[M-i-1]*p; ans %= mod; p *= 50; p %= mod; } ans += n; ans %= mod; return (int)ans; }};