結果

問題 No.5007 Steiner Space Travel
ユーザー monnumonnu
提出日時 2022-07-30 17:49:27
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 940 ms / 1,000 ms
コード長 7,165 bytes
コンパイル時間 3,856 ms
実行使用メモリ 6,952 KB
スコア 8,735,340
最終ジャッジ日時 2022-07-30 17:50:22
合計ジャッジ時間 34,013 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 910 ms
6,948 KB
testcase_01 AC 910 ms
4,904 KB
testcase_02 AC 936 ms
6,948 KB
testcase_03 AC 910 ms
4,904 KB
testcase_04 AC 909 ms
4,904 KB
testcase_05 AC 910 ms
4,900 KB
testcase_06 AC 909 ms
4,904 KB
testcase_07 AC 909 ms
4,904 KB
testcase_08 AC 909 ms
4,904 KB
testcase_09 AC 910 ms
4,900 KB
testcase_10 AC 911 ms
4,904 KB
testcase_11 AC 911 ms
4,904 KB
testcase_12 AC 910 ms
4,180 KB
testcase_13 AC 911 ms
4,904 KB
testcase_14 AC 909 ms
4,900 KB
testcase_15 AC 910 ms
6,948 KB
testcase_16 AC 910 ms
4,904 KB
testcase_17 AC 910 ms
6,948 KB
testcase_18 AC 908 ms
4,900 KB
testcase_19 AC 909 ms
6,948 KB
testcase_20 AC 909 ms
4,904 KB
testcase_21 AC 909 ms
4,904 KB
testcase_22 AC 910 ms
6,952 KB
testcase_23 AC 910 ms
4,900 KB
testcase_24 AC 910 ms
4,904 KB
testcase_25 AC 911 ms
4,904 KB
testcase_26 AC 910 ms
4,900 KB
testcase_27 AC 909 ms
6,952 KB
testcase_28 AC 914 ms
4,904 KB
testcase_29 AC 940 ms
6,952 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: 関数 ‘int main()’ 内:
main.cpp:266:29: 警告: ‘currentBase’ はこの関数内初期化されずに使用されるかもしれません [-Wmaybe-uninitialized]
  266 |     currentBase=(currentBase+1)%M;
      |                 ~~~~~~~~~~~~^~~

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
using ll=long long;
using Graph=vector<vector<int>>;
#define INF 1000000000
#define MOD 998244353
#define MAX 500

int N,M;
int alpha = 5;

random_device seed;
mt19937 engine(seed());
uniform_real_distribution<> uniform_real_dist(0.0,1.0);
clock_t start_t,end_t;
double elapsed_time;
//実行制限時間-ε
double time_limit=0.9;
//初期温度
int annCnt=0;
int loopCnt=1;
//double T0[5] = {1e6,1e5,1e4,1e3,1e2};
double T0=1e6;
//最終温度
double T1=1e2;

void update_base_place(vector<int> &ans,vector<int> &a,vector<int> &b,vector<int> &x,vector<int> &y,vector<vector<int>> &dist,vector<vector<int>> &nextNode)
{
  // 基地の位置を変更
  vector<int> pathCnt(M,0);
  for(int i=0;i<M;i++){
    x[i] = 0;
    y[i] = 0;
  }
  for(int i=0;i<(int)ans.size()-1;i++){
    if(ans[i]<N&&ans[i+1]>=N){
      int v=ans[i+1]-N;
      int u=ans[i];
      pathCnt[v]++;
      x[v]+=a[u];
      y[v]+=b[u];
    }
    else if(ans[i]>=N&&ans[i+1]<N){
      int v=ans[i]-N;
      int u=ans[i+1];
      pathCnt[v]++;
      x[v]+=a[u];
      y[v]+=b[u];
    }
  }
  for(int i=0;i<M;i++){
    if(pathCnt[i]>0){
      x[i]/=pathCnt[i];
      y[i]/=pathCnt[i];
    }
    else{
      x[i]=rand()%1000;
      y[i]=rand()%1000;
    }
  }

  // distテーブルの更新
  for(int i=0;i<N+M;i++){
    for(int j=0;j<N+M;j++){
      dist[i][j]=INF;
    }
  }
  for(int i=0;i<N;i++){
    for(int j=0;j<N;j++){
      dist[i][j] = alpha*alpha * ((a[i]-a[j])*(a[i]-a[j]) + (b[i]-b[j])*(b[i]-b[j]));
    }
  }
  for(int i=0;i<N;i++){
    for(int j=0;j<M;j++){
      dist[i][N+j] = alpha * ((a[i]-x[j])*(a[i]-x[j]) + (b[i]-y[j])*(b[i]-y[j]));
      dist[N+j][i] = alpha * ((a[i]-x[j])*(a[i]-x[j]) + (b[i]-y[j])*(b[i]-y[j]));
    }
  }
  for(int i=0;i<M;i++){
    for(int j=0;j<M;j++){
      dist[N+i][N+j] = (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]);
    }
  }
  for(int i=0;i<N+M;i++){
    for(int j=0;j<N+M;j++){
      nextNode[i][j]=j;
    }
  }

  for(int k=0;k<N+M;k++){
    for(int i=0;i<N+M;i++){
      for(int j=0;j<N+M;j++){
        if(dist[i][k]+dist[k][j]<dist[i][j]){
          dist[i][j]=dist[i][k]+dist[k][j];
          nextNode[i][j]=nextNode[i][k];
        }
      }
    }
  }
}

vector<int> solve_ans(vector<int> &path,vector<vector<int>> &nextNode)
{
  vector<int> ans;
  ans.push_back(path[0]);
  for(int i=0;i<(int)path.size()-1;i++){
    int v=path[i];
    while(v!=path[i+1]){
      v=nextNode[v][path[i+1]];
      ans.push_back(v);
    }
  }
  return ans;
}

void two_opt(vector<int> &path, vector<int> &a,vector<int> &b,vector<int> &x,vector<int> &y, vector<vector<int>> &dist, vector<vector<int>> &nextNode, int &S)
{
  start_t=clock();
  int n=path.size();
  end_t=clock();
  elapsed_time=(double)(end_t-start_t)/CLOCKS_PER_SEC;
  double update_time=0.07;
  // path[1, n-2]の順番を変更
  while (elapsed_time <= time_limit) {
    double T=pow(T0,1.0-elapsed_time/time_limit)*pow(T1,elapsed_time/time_limit);
    int left  = rand()%(n-2) + 1;
    int right = rand()%(n-2) + 1;
    if (left == right) {
      continue;
    }
    if (right < left) {
      swap(left, right);
    }
    int deltaS = 0.0;
    deltaS -= dist[path[left-1]][path[left]] + dist[path[right]][path[right+1]];
    deltaS += dist[path[left-1]][path[right]] + dist[path[left]][path[right+1]];
    int diff = round(1.0e9/(1.0e3 + sqrt(S+deltaS))) - round(1.0e9/(1.0e3 + sqrt(S)));
    //遷移確率
    double p=min<double>(1.0,exp(diff/T));
    if(uniform_real_dist(engine)<=p){
      S += deltaS;
      reverse(path.begin() + left, path.begin() + (right+1));
    }
    end_t=clock();
    elapsed_time=(double)(end_t-start_t)/CLOCKS_PER_SEC;

    if(elapsed_time>=update_time){
      update_time+=0.07;
      vector<int> ans=solve_ans(path,nextNode);
      update_base_place(ans,a,b,x,y,dist,nextNode);
      S=0;
      for(int i=0;i<N;i++){
        S+=dist[path[i]][path[i+1]];
      }
    }
  }
  annCnt++;
}

int main(){
  cin>>N>>M;
  vector<int> a(N), b(N);
  for(int i=0;i<N;i++){
    cin>>a[i]>>b[i];
  }

  /*
  vector<pair<int,int>> planetCnt(N);
  for(int i=0;i<N;i++){
    planetCnt[i].second=i;
    planetCnt[i].first=0;
  }
  for(int i=0;i<N;i++){
    for(int j=i+1;j<N;j++){
      if((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])<=100*100){
        planetCnt[i].first++;
        planetCnt[j].first++;
      }
    }
  }
  sort(planetCnt.begin(),planetCnt.end());

  vector<int> x(M),y(M);
  int k=0;
  for(int i=N-1;i>=0;i--){
    bool flag=true;
    for(int j=0;j<k;j++){
      if((a[i]-x[j])*(a[i]-x[j])+(b[i]-y[j])*(b[i]-y[j])<=100*100){
        flag=false;
        break;
      }
    }
    if(flag){
      x[k]=a[i];
      y[k]=b[i];
      k++;
      if(k==M){
        break;
      }
    }
  }
  */

  int delta = 300;
  vector<int> x={500+delta, 500+delta, 500, 500-delta, 500-delta, 500-delta, 500, 500+delta};
  vector<int> y={500, 500+delta, 500+delta, 500+delta, 500, 500-delta, 500-delta, 500-delta};
  vector<vector<int>> dist(N+M,vector<int>(N+M,INF));
  vector<vector<int>> nextNode(N+M,vector<int>(N+M));
  for(int i=0;i<N;i++){
    for(int j=0;j<N;j++){
      dist[i][j] = alpha*alpha * ((a[i]-a[j])*(a[i]-a[j]) + (b[i]-b[j])*(b[i]-b[j]));
    }
  }
  for(int i=0;i<N;i++){
    for(int j=0;j<M;j++){
      dist[i][N+j] = alpha * ((a[i]-x[j])*(a[i]-x[j]) + (b[i]-y[j])*(b[i]-y[j]));
      dist[N+j][i] = alpha * ((a[i]-x[j])*(a[i]-x[j]) + (b[i]-y[j])*(b[i]-y[j]));
    }
  }
  for(int i=0;i<M;i++){
    for(int j=0;j<M;j++){
      dist[N+i][N+j] = (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]);
    }
  }
  for(int i=0;i<N+M;i++){
    for(int j=0;j<N+M;j++){
      nextNode[i][j]=j;
    }
  }

  for(int k=0;k<N+M;k++){
    for(int i=0;i<N+M;i++){
      for(int j=0;j<N+M;j++){
        if(dist[i][k]+dist[k][j]<dist[i][j]){
          dist[i][j]=dist[i][k]+dist[k][j];
          nextNode[i][j]=nextNode[i][k];
        }
      }
    }
  }

  vector<vector<int>> nearbyPlanets(M);
  int currentBase;
  for(int i=0;i<N;i++){
    int k=0;
    for(int j=1;j<M;j++){
      if(dist[i][j]<dist[i][k]){
        k=j;
      }
    }
    nearbyPlanets[k].push_back(i);
    if(i==0){
      currentBase=k;
    }
  }
  vector<int> path;
  path.push_back(0);
  for(int i=0;i<M;i++){
    for(int p:nearbyPlanets[currentBase]){
      if(p!=0){
        path.push_back(p);
      }
    }
    currentBase=(currentBase+1)%M;
  }
  path.push_back(0);
  //assert(path.size()==N+1);

  int S=0;
  for(int i=0;i<N;i++){
    S+=dist[path[i]][path[i+1]];
  }

  two_opt(path,a,b,x,y,dist,nextNode,S);

  // 経路を出す
  vector<int> ans = solve_ans(path,nextNode);
  // 基地の位置を変更
  update_base_place(ans,a,b,x,y,dist,nextNode);
  //経路再計算
  ans=solve_ans(path,nextNode);
  // 出力
  for(int i=0;i<M;i++){
    cout<<x[i]<<' '<<y[i]<<'\n';
  }
  cout<<ans.size()<<'\n';
  for(int i=0;i<ans.size();i++){
    if(ans[i]<N){
      cout<<"1 "<<ans[i]+1<<'\n';
    }else{
      cout<<"2 "<<(ans[i]-N)+1<<'\n';
    }
  }

  S=0;
  for(int i=0;i<N;i++){
    S+=dist[path[i]][path[i+1]];
  }
  int score = round(1.0e9/(1.0e3 + sqrt(S)));
  //cout<<score<<'\n';
}
0