Isa@Diary

ソフトウェア開発やってます。プログラミングとか、US生活とかについて書きます。

Topcoder Open Round.2B

結果

o--(+0/-0) 184.32pts 444th
1671->1705(+34)

Highest更新、1700台にのりました。
300-550-900とか0完フラグだろ…と思ったものの
300が解けてよかった。

300

場合分けでガンガン。
0がないときは明らか、
0がk個あるとするとき、
k箇所に1本ずつ当てたとき
(その平均が、既に解っている点数の最大より大きい||解っている数値がない)
場合はk本1セットとして取っていけばよい。

1セットに満たない点数については
0の場所にk本未満投げたときは、少なくとも
(板に存在しない数の小さい方からk個の和)点は取れる。
その平均が既に解っている点数の最大より低ければ
残りの点数は0に当てる必要はなく、解っている点数にあてればよい。

sampleがそこそこ強いと思ったんだけどそうでもなかったようだ。

以下ソース

     int minThrows(vector <int> points, int P) {
         int n = points.size();
         bool isexist[n+1];
         int maxi = -1;
         memset(isexist, false,sizeof(isexist));
         for(int i=0;i<n;i++){
             isexist[points[i]] = true;
             if(points[i] != 0){
                 maxi = max(maxi, points[i]);
             }
         }

         if(isexist[0] == false){
             return (int)ceil((double)P/maxi);
         }else{
             vector<int> cands;
             vector<pair<double,int> > v;
             int sum=0;
             for(int i=1;i<=n;i++){
                 if(!isexist[i]) cands.push_back(i);
             }
             
             for(int i=0;i<cands.size();i++){
                 sum += cands[i];
                 v.push_back(make_pair((double)sum / (i+1),sum));
             }
             if(maxi - v.back().first > -EPS){
                 return (int)ceil((double)P/maxi);
             }

             int ret = 0;
             int set = P / v.back().second;
             P -= v.back().second * set;
             if(P == 0) return set * v.size();
             for(int i=0;i<v.size();i++){
                 if(P <= v[i].second){
                     if(maxi == -1){
                         return set*v.size() + i + 1;
                     }else{
                         return min(set*v.size() + (int)ceil((double)P/maxi), set*v.size() + i + 1);
                     }
                 }
             }
         }
     }