要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
1e-1精度:下界1e-3或1e-4 降温系数0.8
1e-5精度:下界1e-7或1e-8 降温系数0.99
洛谷https://www.luogu.org/problem/P2210
#include<bits/stdc++.h>
using namespace std;
namespace IO {
struct q_instream {
template < typename classT >
inline q_instream operator>>(classT &e) const {
e= 0;
classT f= 1, c= 0;
while(c < '0' || c > '9') {
if(c == '-') f= -1;
c= getchar();
}
while(c >= '0' && c <= '9') e= e * 10 + c - '0', c= getchar();
return e= e * f, (*this);
}
} in;
//读入优化
struct q_outstream {
template < typename classT >
inline q_outstream operator<<(const classT &e) const {
if(e < 0) {
putchar('-');
(*this) << -e;
}
else {
if(e > 9) (*this) << (e / 10);
putchar(e % 10 + '0');
}
return (*this);
}
inline q_outstream operator<<(const char &c) const {
return putchar(c), (*this);
}
} out;
//输出优化
}
using namespace IO;
int n;
int mp[13][4];
int pos[13];
long long get_cost(){//因题而异
long long ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=3;j++){
ans+=abs(pos[i]-pos[mp[i][j]]);
}
}
return ans;
}
//SA模板
int best_ans=0x3f3f3f3f;
const double BeginT= 10000, EndT= 1e-14, ChangeT= 0.99;
//起始温度,终止温度,温度改变速度
void SA(int times) {
//模拟退火过程
long long x, y, tmp_ans;
while(times--) {
for(double T= BeginT; T > EndT; T*= ChangeT) {
do {
x= rand() % n + 1;//随机产生两个不相同的点
y= rand() % n + 1;
} while(x == y);
swap(pos[x], pos[y]);//任意交换两个牛的位置
tmp_ans= get_cost();//求出当前解
if(tmp_ans <= best_ans) {//更优就更新答案
best_ans= tmp_ans;
}
else if(exp((best_ans - tmp_ans) / T) > (double)rand() / RAND_MAX) {//条不接收较差的条件
swap(pos[x], pos[y]);//不接受较差解,将两个牛位置交换回去
}
}
}
return;
}
int main(){
srand(rand()); srand(rand()); //玄学srand
in>>n;
for(int i=1;i<=n;i++){
pos[i]=i;
for(int j=1;j<=3;j++){
in>>mp[i][j];
}
}
SA(200);
printf("%d\n",best_ans/2);
return 0;
}
洛谷https://www.luogu.org/problem/P1337
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
double x,y,w;
};
vector<node> vec;
double get_cost(double cx,double cy){
double sum=0;
for(int i=0;i<n;i++){
double x,y,w;
x=vec[i].x-cx;y=vec[i].y-cy;w=vec[i].w;
sum+=sqrt(x*x+y*y)*w;
}
return sum;
}
double ansx,ansy;
//SA模板
double best_ans=1e18+7;
const double BeginT= 10000, EndT= 1e-15, ChangeT= 0.996;
// 起始温度, 终止温度, 温度改变速度W
void SA(int times) {
//模拟退火过程
double x, y, tmp_ans;
while(times--) {
for(double T= BeginT; T > EndT; T*= ChangeT) {
x=ansx+(rand()*2-RAND_MAX)*T;//rand()*2-RAND_MAX的范围是
y=ansy+(rand()*2-RAND_MAX)*T;//-RAND_MAX到RAND_MAX
tmp_ans=get_cost(x,y);
if(tmp_ans < best_ans) {//更优就更新答案
best_ans= tmp_ans;
ansx=x;
ansy=y;
}
else if(exp((best_ans - tmp_ans) / T) > (double)rand() / RAND_MAX) {//否则根据多项式概率接受
ansx=x;
ansy=y;
}
}
}
return;
}
int main(){
srand(rand()); srand(rand()); //玄学srand
scanf("%d",&n);
for(int i=1;i<=n;i++){
double x,y,z;
scanf("%lf%lf%lf",&x,&y,&z);
vec.push_back(node{x,y,z});
ansx+=x;ansy+=y;
}
SA(6);
printf("%.3lf %.3lf\n",ansx,ansy);
return 0;
}
HDUhttp://acm.hdu.edu.cn/showproblem.php?pid=2899
#include<bits/stdc++.h>
using namespace std;
double get_cost(double x,double y){
return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*pow(x,2)-y*x;
}
double y;
//SA模板
double best_ans=1e18+7;
const double BeginT= 10000, EndT= 1e-15, ChangeT= 0.98;
//起始温度,终止温度,温度改变速度
void SA(int times) {
best_ans=1e18+7;
//模拟退火过程
double x, tmp_ans;
while(times--) {
for(double T= BeginT; T > EndT; T*= ChangeT) {
for(int i=1;i<=2;i++){
double tx;
if(i==1){
tx=x+T;
}
else tx=x-T;
if(tx>100||tx<0)continue;
tmp_ans=get_cost(tx,y);
if(tmp_ans <= best_ans) {//更优就更新答案
best_ans= tmp_ans;
x=tx;
}
else if(exp((best_ans - tmp_ans) / T) > (double)rand() / RAND_MAX) {//条不接收较差的条件
continue;
}
}
}
}
return;
}
int main(){
srand(rand());
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf",&y);
SA(5);
printf("%.4lf\n",best_ans);
}
return 0;
}
二维坐标
HDUhttp://acm.hdu.edu.cn/showproblem.php?pid=3932
#include<bits/stdc++.h>
using namespace std;
#define PI (3.14159265358979323846)
#define PI_DIV_180 (0.017453292519943296)//π/180
#define DegToRad(x) ((x)*PI_DIV_180)//角度转换为弧度
int nxt[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,-1},{1,-1},{-1,1}};
double X,Y;
int n;
struct node{
double x,y;
};
vector<node> vec;
double get_cost(double x,double y){
double ans=0;
for(int i=0;i<n;i++){
double tx,ty;
tx=x-vec[i].x;
ty=y-vec[i].y;
ans=max(ans,sqrt(tx*tx+ty*ty));
}
return ans;
}
double ansx,ansy;
//SA模板
double best_ans=1e18+7;
const double BeginT= 10000, EndT= 1e-8, ChangeT= 0.993;
//起始温度,终止温度,温度改变速度
void SA(int times) {
best_ans=1e18+7;
//模拟退火过程
double x,y, tmp_ans;
x=X;y=Y;
while(times--) {
for(double T= BeginT; T > EndT; T*= ChangeT) {
double tx,ty;
for(int i=0;i<8;i++){
tx=x+(double)(rand()%1000+1)/1000.0*nxt[i][0]*T;
ty=y+(double)(rand()%1000+1)/1000.0*nxt[i][1]*T;
if(tx>X||ty>Y||tx<0||ty<0)continue;
tmp_ans=get_cost(tx,ty);
if(tmp_ans < best_ans) {//更优就更新答案
best_ans= tmp_ans;
x=tx;y=ty;
ansx=tx;ansy=ty;
}
else if(exp((best_ans - tmp_ans) / T) > (double)rand() / RAND_MAX) {//条不接收较差的条件
//x=tx;y=ty;
}
}
}
}
return;
}
int main(){
srand(rand());
while(~scanf("%lf%lf%d",&X,&Y,&n)){
vec.clear();
for(int i=1;i<=n;i++){
double a,b;
scanf("%lf%lf",&a,&b);
vec.push_back(node{a,b});
}
SA(6);
printf("(%.1lf,%.1lf).\n%.1lf\n",ansx,ansy,best_ans);
}
return 0;
}
大佬博客:
https://www.luogu.org/blog/m-sea/qian-tan-SA
https://www.luogu.org/blog/Ciyang/solution-p2210
https://www.cnblogs.com/flashhu/p/8884132.html