模拟退火挂啦求调
  • 板块学术版
  • 楼主_8008008
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/9/28 11:53
  • 上次更新2024/9/28 14:43:04
查看原帖
模拟退火挂啦求调
803885
_8008008楼主2024/9/28 11:53

https://www.luogu.com.cn/problem/T505591
有点玄学的价值计算方法,但是每次交上去都是同样的结果

#include<iostream>
#include<ctime>
#include<random>
#include<queue>
#include<vector>
#include<cmath>
#define double long double
using namespace std;
const int maxn=100001;
int n,m,t,k,x;
double a[maxn],p[maxn];
bool chs[maxn];double answ,best=2;
vector<int>l,r;
int cs,cs2;
double w(){
	double g=1;
	priority_queue<double,vector<double>,greater<double> >pts;
	for(int i=0;i<l.size();i++){
		g*=1-p[l[i]];
		pts.push(a[l[i]]);
	}
	g=1-g;
	for(int i=1;i<=k;i++){
		double tp=pts.top();pts.pop();
		pts.push(tp+x);
	}
	if(pts.top()>=t)best=min(best,g);
	return g*(pts.top()>=t?8000:10000);//这样会让方案更不容易被更新(可能 
}
void SA(){
	double temp=1e5;
	while(temp>1e-8){
		int sa=rand()%l.size();
		int sb=rand()%r.size();
		swap(l[sa],r[sb]);
		double noww=w(),delta=answ-noww;
		if(delta<0)answ=noww;
		else if(exp(-(double)delta*RAND_MAX/temp)<rand())answ=noww;
		else swap(l[sa],r[sb]);
		temp*=0.995;
	}
}
int main(){
	srand(time(NULL));
	scanf("%d%d%d%d%d",&n,&m,&t,&k,&x);
	for(int i=1;i<=n;i++){
		scanf("%Lf%Lf",&a[i],&p[i]);
	}
	for(int i=1;i<=m;i++){
		l.push_back(i);
	}
	for(int i=m+1;i<=n;i++){
		r.push_back(i);
	}
	answ=w();
//	SA();
	while((double)clock()/CLOCKS_PER_SEC<0.90)SA();
	if(best==2)printf("-1");
	else printf("%.7Lf",best);
	return 0;
}
2024/9/28 11:53
加载中...