Isa@Diary

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

SRM423 Div.1 Easy

問題

無限に広がるマス上にn個のチェッカーがあり、そのうちi個(1 <= i <= n)のチェッカーを同じマスに移動するまでの移動数の合計の最小を求める。

方針

解となるx,y座標は入力として与えられるx,y座標の中にあるはずなので、それぞれ50*50=2500通りの
解が考えられる。
これらの候補に対し入力されたすべてのチェッカーからの移動距離(マンハッタン距離)を調べてソートした上で小さいものからi個の和の最小値を入れていけばよい。

計算量はO(50^4)ぐらい。充分間に合う。

以下ソースコード

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>

using namespace std;

#define dump(x)  cerr << #x << " = " << (x) << endl;
inline int toInt(string s){int v;istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x){ostringstream sout;sout<<x;return sout.str();}

class TheTower {
     public:

     vector <int> count(vector <int> x, vector <int> y) {
       vector<int> ret;
       int n=x.size();
       set<int> xs, ys;

       for(int i=0;i<n;i++){
	 xs.insert(x[i]);
	 ys.insert(y[i]);
       }

       vector<int> xvec,yvec;
       set<int>::iterator it = xs.begin(), jt = ys.begin();
       while(it!=xs.end()){
	 xvec.push_back(*it);
	 ++it;
       }
       while(jt!=ys.end()){
	 yvec.push_back(*jt);
	 ++jt;
       }

       for(int num=1;num<=n;num++){
	 //何個とるか
	 int tmpret=1 << 29;
	 for(int i=0;i<xvec.size();i++){
	   for(int j=0;j<yvec.size();j++){
	     int costs[n];
	     //ある一点を選んで
	     for(int k=0;k<n;k++){
	       costs[k] = abs(xvec[i] - x[k]) + abs(yvec[j] - y[k]);
	     }
	     //greedyに近い点を選ぶ
	     sort(costs,costs+n);
	     tmpret = min(tmpret,accumulate(costs,costs+num,0));
	   }
	 }
	 ret.push_back(tmpret);
       }
       return ret;
     }