結果

問題 No.5007 Steiner Space Travel
ユーザー どらら
提出日時 2022-07-30 16:34:26
言語 C++14
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 954 ms / 1,000 ms
コード長 7,047 bytes
コンパイル時間 4,239 ms
実行使用メモリ 6,952 KB
スコア 8,219,471
最終ジャッジ日時 2022-07-30 16:35:11
合計ジャッジ時間 35,302 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 30
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it)
#define ALLOF(c) (c).begin(), (c).end()
typedef long long ll;
typedef unsigned long long ull;
//using mint = modint1000000007;
//using mint = modint998244353;
class Timer {
std::chrono::system_clock::time_point start_time;
std::chrono::system_clock::time_point getNow() {
return std::chrono::system_clock::now();
}
public:
void start() {
start_time = getNow();
}
float getSec() {
float count =
std::chrono::duration_cast<std::chrono::microseconds>(getNow() - start_time).count();
return count / 1e6;
}
};
uint32_t xor128() {
static uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;
uint32_t t;
t = (x ^ (x << 11));
x = y;
y = z;
z = w;
return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}
struct P {
int t,i;
double y, x;
P():t(0),i(0),y(0),x(0){}
P(int t, int i, double y, double x):t(t),i(i),y(y),x(x){}
};
double distance(const P& a, const P& b) {
static constexpr double alpha = 5.0;
if(a.t == 1 && b.t == 1){
return alpha*alpha*((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
else if(a.t == 1 || b.t == 1){
return alpha * ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
else{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
}
vector<int> kmeans(const vector<P>& p, int M){
vector<P> r;
rep(i,M) r.emplace_back(p[i]);
vector<int> ret(p.size());
//rep(i,ret.size()) ret[i] = i%M;
rep(i,ret.size()) ret[i] = xor128()%M;
rep(t,1000000){
bool change = false;
vector<P> g(M);
rep(i,p.size()){
g[ret[i]].y += p[i].y;
g[ret[i]].x += p[i].x;
g[ret[i]].i++;
}
rep(i,M){
if(g[i].i == 0){
int r = xor128()%p.size();
g[i].y = p[r].y;
g[i].x = p[r].x;
}else{
g[i].y /= g[i].i;
g[i].x /= g[i].i;
}
}
rep(i,p.size()){
double mind = 1e9;
int minj = 0;
rep(j,M){
double d = distance(p[i],g[j]);
if(mind > d){
mind = d;
minj = j;
}
}
if(ret[i] != minj){
change = true;
ret[i] = minj;
}
}
if(!change) break;
}
return ret;
}
vector<int> small_tsp(const vector<P>& v){
int N = v.size();
double tour_distance = 0;
vector<int> tour(N);
for (int i = 0; i < N; i++) {
tour[i] = i;
tour_distance += distance(v[tour[i]], v[tour[(i + 1) % N]]);
}
double best_distance = tour_distance;
vector<int> best_tour = tour;
do {
tour_distance = 0;
for (int i = 0; i < N; i++) {
tour_distance += distance(v[tour[i]], v[tour[(i + 1) % N]]);
}
if (best_distance > tour_distance) {
best_distance = tour_distance;
best_tour = tour;
}
} while (next_permutation(tour.begin(), tour.end()));
while(best_tour[0] != 0) rotate(best_tour.begin(), best_tour.begin()+1,best_tour.end());
return best_tour;
}
struct ST {
int i;
double ox, oy;
ll x, y;
};
bool operator<(const ST& a, const ST& b){
int sa = -1;
if(a.x>=0 && a.y>=0) sa = 1;
else if(a.x<=0 && a.y>=0) sa = 2;
else if(a.x<=0 && a.y<=0) sa = 3;
else if(a.x>=0 && a.y<=0) sa = 4;
int sb = -1;
if(b.x>=0 && b.y>=0) sb = 1;
else if(b.x<=0 && b.y>=0) sb = 2;
else if(b.x<=0 && b.y<=0) sb = 3;
else if(b.x>=0 && b.y<=0) sb = 4;
if(sa != sb) return sa < sb;
return a.x * b.y - b.x * a.y > 0;
}
int N, M;
vector<P> planets;
ll calc_score(const vector<P>& ss, const vector<pair<int,int>>& ans){
double ret = 0;
rep(i,ans.size()-1){
P p1, p2;
if(ans[i].first == 1) p1 = planets[ans[i].second-1];
if(ans[i].first == 2) p1 = ss[ans[i].second-1];
if(ans[i+1].first == 1) p2 = planets[ans[i+1].second-1];
if(ans[i+1].first == 2) p2 = ss[ans[i+1].second-1];
ret += distance(p1, p2);
}
return (ll)(1e9 / (1000.0 + sqrt(ret)));
}
Timer timer;
static constexpr double TIME_LIMIT = 0.95;
int main(){
timer.start();
cin >> N >> M;
rep(i,N){
ll y, x;
cin >> y >> x;
planets.emplace_back(1,i+1,y,x);
}
vector<pair<int,int>> best_ans;
vector<P> best_ss;
ll best_score = 0;
while(true){
double sec = timer.getSec();
if(sec > TIME_LIMIT) break;
vector<int> cluster = kmeans(planets,M);
if(sec > TIME_LIMIT) break;
vector<P> ss(M);
vector<int> ss_num(M,0);
rep(i,planets.size()){
ss[cluster[i]].y += planets[i].y;
ss[cluster[i]].x += planets[i].x;
ss_num[cluster[i]]++;
}
rep(i,M){
ss[i].t = 2;
ss[i].i = i+1;
if(ss_num[i] == 0) continue;
ss[i].y /= ss_num[i];
ss[i].x /= ss_num[i];
}
if(cluster[0] != 0){
int c = cluster[0];
rep(i,cluster.size()){
if(cluster[i] == c) cluster[i] = 0;
else if(cluster[i] == 0) cluster[i] = c;
}
swap(ss[0], ss[c]);
swap(ss_num[0], ss_num[c]);
ss[0].i = 1;
ss[c].i = c+1;
}
vector<P> groups[10];
rep(i,planets.size()){
if(planets[i].i == 1) continue;
groups[cluster[i]].push_back(planets[i]);
}
if(sec > TIME_LIMIT) break;
vector<int> ss_tsp = small_tsp(ss);
if(sec > TIME_LIMIT) break;
vector<pair<int,int>> ans;
ans.emplace_back(1,1);
rep(i,ss_tsp.size()){
if(ss_num[ss_tsp[i]] == 0) continue;
ans.emplace_back(2,ss[ss_tsp[i]].i);
vector<ST> sts;
rep(j,groups[ss_tsp[i]].size()){
sts.push_back((ST){groups[ss_tsp[i]][j].i,groups[ss_tsp[i]][j].x,groups[ss_tsp[i]][j].y,(ll)(groups[ss_tsp[i]][j].x-ss[ss_tsp[i]].x),(ll
            )(groups[ss_tsp[i]][j].y-ss[ss_tsp[i]].y)});
}
sort(ALLOF(sts));
ans.emplace_back(1,sts[0].i);
rep(j,sts.size()-1){
double d1 = distance((P){1,0,sts[j].oy,sts[j].ox},(P){1,0,sts[j+1].oy,sts[j+1].ox});
double d2 = distance((P){1,0,sts[j].oy,sts[j].ox},(P){2,0,ss[ss_tsp[i]].y,ss[ss_tsp[i]].x}) +
distance((P){2,0,ss[ss_tsp[i]].y,ss[ss_tsp[i]].x},(P){1,0,sts[j+1].oy,sts[j+1].ox});
if(d1 < d2){
ans.emplace_back(1,sts[j+1].i);
}else{
ans.emplace_back(2,ss[ss_tsp[i]].i);
ans.emplace_back(1,sts[j+1].i);
}
}
ans.emplace_back(2,ss[ss_tsp[i]].i);
}
ans.emplace_back(2,ss[ss_tsp[0]].i);
ans.emplace_back(1,1);
if(sec > TIME_LIMIT) break;
ll score = calc_score(ss,ans);
//cerr << score << endl;
if(best_score < score){
best_score = score;
best_ans = ans;
best_ss = ss;
}
}
cerr << best_score << endl;
rep(i,M){
cout << (int)(best_ss[i].y) << " " << (int)(best_ss[i].x) << endl;
}
cout << best_ans.size() << endl;
rep(i,best_ans.size()){
cout << best_ans[i].first << " " << best_ans[i].second << endl;
}
return 0;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0