結果

問題 No.5007 Steiner Space Travel
ユーザー rinrionrinrion
提出日時 2022-08-07 15:38:04
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 453 ms / 1,000 ms
コード長 5,761 bytes
コンパイル時間 2,700 ms
実行使用メモリ 6,952 KB
スコア 7,512,506
最終ジャッジ日時 2022-08-07 15:38:25
合計ジャッジ時間 17,790 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 451 ms
6,948 KB
testcase_01 AC 452 ms
4,900 KB
testcase_02 AC 452 ms
6,952 KB
testcase_03 AC 452 ms
4,904 KB
testcase_04 AC 453 ms
4,904 KB
testcase_05 AC 452 ms
6,948 KB
testcase_06 AC 452 ms
4,904 KB
testcase_07 AC 452 ms
4,900 KB
testcase_08 AC 452 ms
6,948 KB
testcase_09 AC 452 ms
4,904 KB
testcase_10 AC 452 ms
4,900 KB
testcase_11 AC 453 ms
4,900 KB
testcase_12 AC 452 ms
6,948 KB
testcase_13 AC 452 ms
4,904 KB
testcase_14 AC 452 ms
4,908 KB
testcase_15 AC 452 ms
4,908 KB
testcase_16 AC 452 ms
4,900 KB
testcase_17 AC 452 ms
4,900 KB
testcase_18 AC 452 ms
4,904 KB
testcase_19 AC 452 ms
4,900 KB
testcase_20 AC 452 ms
4,904 KB
testcase_21 AC 452 ms
4,900 KB
testcase_22 AC 452 ms
4,900 KB
testcase_23 AC 451 ms
6,952 KB
testcase_24 AC 452 ms
4,904 KB
testcase_25 AC 451 ms
4,900 KB
testcase_26 AC 451 ms
4,904 KB
testcase_27 AC 452 ms
6,948 KB
testcase_28 AC 452 ms
4,904 KB
testcase_29 AC 452 ms
6,952 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include<chrono> 
using namespace std;

long double ENG(int x1,int y1, int x2, int y2,int t){//エネルギー計算 座標と定数を入力
	long double uq= sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
	return uq*uq*t;	
}

long SCORE(long double s){
	return (long)(1000000000/(1000+sqrt(s)));
}

static uint32_t randxor(){//ランダム数(int)
	static uint32_t x = 123456789;
	static uint32_t y = 362436069;
	static uint32_t z = 521288629;
	static uint32_t w = 88675123;
	uint32_t t = x ^ (x << 11);
	x = y; y = z; z = w;
	return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}

static double rand01(){//ランダム数(0.0以上1.0未満の小数)
	return(randxor()+0.5)*(1.0/UINT_MAX);
}

double timelmt_1=450,timelmt_2=980;
double gettime;
chrono::system_clock::time_point  time_now;
chrono::system_clock::time_point  time_start = chrono::system_clock::now(); 

double start_temp=500, end_temp=0.001,temp;

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

	vector<vector<long double>>eng(100,vector<long double>(100)),eng_t;
	vector<vector<pair<long double,int>>>eng_sr(100,vector<pair<long double,int>>(100));

	for(int i=0;i<100;i++){
		for(int j=0;j<100;j++){
			if(i!=j) eng[i][j]=ENG(a[i],b[i],a[j],b[j],25);
			else eng[i][j]=1000000000001;
			
			eng_sr[i][j]=make_pair(eng[i][j],j);
		}
		sort(eng_sr[i].begin(),eng_sr[i].end());//eng_srのみエネルギーを昇順に並べ替え
	}

	vector<int>c,d;//ロボてりーの位置 最初は均等に置く
	c.push_back(250),d.push_back(250);
	c.push_back(250),d.push_back(500);
	c.push_back(250),d.push_back(750);
	c.push_back(500),d.push_back(250);
	c.push_back(500),d.push_back(750);
	c.push_back(750),d.push_back(250);
	c.push_back(750),d.push_back(500);
	c.push_back(750),d.push_back(750);


	vector<int>tr,tr_best;//惑星を回る順番
	bitset<100>visited;
	int now=0;
	visited[now]=true;
	tr.push_back(0);

	while(true){//一番近い惑星に行く
		bool jdg=false;
		for(int i=0; i<99; i++){
			if(!(visited[eng_sr[now][i].second])){
				int next=eng_sr[now][i].second;
				tr.push_back(next);
				now=next;
				visited[next]=true;
				jdg=true;
				break;
			}
		}
		if(!jdg)break;
	}
	tr.push_back(0);

	long double eng_sum=0;//消費エネルギー総和
	for(int i=0; i<100; i++){
		eng_sum+=eng[tr[i]][tr[i+1]];
	}

	long score,score_t,score_best;
	score=SCORE(eng_sum);
	score_best=score;
	tr_best=tr;

	int cnt1=0,cnt1_rec;
	int cnt2=0,cnt2_rec;

	while(gettime<timelmt_1){//回る順の焼きなまし
		if((int)cnt1%5000==0){
			time_now = chrono::system_clock::now(); 
			gettime = chrono::duration_cast<chrono::milliseconds>(time_now-time_start).count();
			temp=start_temp+(end_temp-start_temp)*gettime/timelmt_1;
		}

		int A=randxor()%99+1, B=randxor()%99+1;

		int na=tr[A-1],a=tr[A],an=tr[A+1];
		int nb=tr[B-1],b=tr[B],bn=tr[B+1];

		long double eng_m=eng[na][a]+eng[a][an]+eng[nb][b]+eng[b][bn];
		long double eng_p=eng[na][b]+eng[b][an]+eng[nb][a]+eng[a][bn];

		int score_r=SCORE(eng_sum-eng_m+eng_p);

		double prob=exp((score_r-score)/temp);
		double rnd_d=rand01();

		bool judge=false;
		if(prob>rnd_d){
			tr[A]=b,tr[B]=a;
			eng_sum=eng_sum-eng_m+eng_p;
			score=score_r;
			if(score>score_best){
				tr_best=tr;
				score_best=score;
			}
			cnt1_rec++;
		}
		
		cnt1++;
	}

	score=score_best;
	bitset<100>check,check_best;
	map<int,int>st,st_best;

	//ステーション位置の焼きなまし
	// while(true){
	for(int q=0; q<1; q++){

		//ここにstation位置変更を書く
		
		eng_t=eng;
		bitset<100>check_t;//この惑星からステーションに行くか
		map<int,int>st_t;//この惑星から行くステーションの番号

		for(int j=0; j<100; j++){//すべての惑星間のルートについて
			int w1=tr_best[j],w2=tr_best[j+1];//惑星w1からw2へのルートについて調べる

			for(int i=0; i<8; i++){//すべてのステーションについて
				long double eng_b=eng_t[w1][w2];//惑星w1→惑星w2のエネルギー(test値,他のステーション経由の最小値と比較)
				//惑星w1→ステーションi→惑星w2のエネルギー
				long double eng_c=ENG(a[w1],b[w1],c[i],d[i],5)+ENG(c[i],d[i],a[w2],b[w2],5);

				if(eng_b>eng_c){//ステーションiを経由した方がエネルギーが少ないなら(他のステーションとも比べる)
					eng_t[w1][w2]=eng_c;//w1-w2のエネルギー(test)を変更する
					check_t[w1]=true;//w1の次はステーション
					st_t[w1]=i;//w1から行くステーションはi
				}
			}//惑星間の全ルート
		}//全ステーション

		eng_sum=0;//消費エネルギー総和をtest値で計算しなおす
		for(int i=0; i<100; i++){
			eng_sum+=eng_t[tr_best[i]][tr_best[i+1]];
		}

		score_t=SCORE(eng_sum);//scoreを計算しなおす

		if(score_t>score){//山登り
			score=score_t;
			check=check_t;
			st=st_t;
			
			cnt2_rec++;
/*
cout<<"rec score "<<score_t<<endl;
for(int i=0; i<8; i++){
	cout<<c[i]<<" "<<d[i]<<endl;
}

int b_c=check_t.count();

cout<<101+b_c<<endl;
for(int i=0; i<101; i++){
	cout<<1<<" "<<tr_best[i]+1<<endl;
	if(check_t[tr_best[i]]) cout<<2<<" "<<st_t[st_best[i]]+1<<endl;
}
*/
		}


		if(score>score_best||cnt2==0){//best更新なら
			score_best=score;
			check_best=check;
			st_best=st;
		}
		
		cnt2++;
	}

	for(int i=0; i<8; i++){
		cout<<c[i]<<" "<<d[i]<<endl;
	}

	int b_c=check_best.count();

	cout<<101+b_c<<endl;
	for(int i=0; i<101; i++){
		cout<<1<<" "<<tr_best[i]+1<<endl;
		if(check_best[tr_best[i]]) cout<<2<<" "<<st_best[tr_best[i]]+1<<endl;
	}

// cout<<"score "<<score_best<<" cnt1 "<<cnt1<<" "<<fixed<<setprecision(2)<<(double)cnt1_rec/cnt1<<" cnt2 "<<cnt2<<" "<<fixed<<setprecision(2)<<(double)cnt2_rec/cnt2<<endl;

}
0