模拟退火大法
这个算法本身就不多讲了,感觉很暴力。
Luogu P5928
#include<bits/stdc++.h>
#define int long long
using namespace std;
const double eps=1e-3,delta=0.999;
const int N=103;
int n,p;
struct node{
int a,b,c,w;
bitset<N>v;
}e[104];
struct book{
int x,y;
}z[103];
int Ans=1e18;
bitset<N>tmp,vis;
int calc(){
int res=0;
for(int i=1;i<=p;i++) vis[i]=0;
for(int i=1;i<=n;i++){
if(tmp[i]) vis|=e[i].v,res+=e[i].w;
}
for(int i=1;i<=p;i++) if(!vis[i]) return 2e9;
return res;
}
void solve(){
double T=2333;
int ans=calc(),now=ans;
while(T>eps){
int x=rand()%n+1;
tmp[x]=!tmp[x];
int k=calc();
if(k<ans) ans=k;
if(k<now||exp((double)(now-k)/T)>(double)rand()/INT_MAX) now=k;
else tmp[x]=!tmp[x];
T*=delta;
}
Ans=min(Ans,ans);
}
int a,b,c,w;
signed main(){
srand(time(NULL));
cin>>n>>p;
for(int i=1;i<=n;i++){
cin>>a>>b>>c>>w;
e[i]={a,b,c,w,bitset<N>{}};
}
for(int i=1;i<=p;i++){
cin>>z[i].x>>z[i].y;
}
for(int i=1;i<=n;i++){
tmp[i]=1;
for(int j=1;j<=p;j++){
if(z[j].x*e[i].a+z[j].y*e[i].b<=e[i].c){
e[i].v[j]=1;
}
}
}
if(calc()==2e9){
cout<<"-1";
return 0;
}
double timer=clock();
while(clock()-timer<=CLOCKS_PER_SEC*0.98) solve();
cout<<Ans;
}
Luogu P1337
#include<bits/stdc++.h>
using namespace std;
double x_ans,y_ans,ans;
int n;
double delta=0.999,Min=1e-14;
struct node{
int x,y,w;
}z[3004];
unsigned long long seed=19491001;
double get(double x,double y){
double dx=0,dy=0,res=0;
for(int i=1;i<=n;i++){
dx=x-z[i].x;
dy=y-z[i].y;
res+=sqrt(dx*dx+dy*dy)*z[i].w;
}
return res;
}
void solve(){
double T=3100;
while(T>Min){
double x=x_ans+(rand()*2-RAND_MAX)*T;
double y=y_ans+(rand()*2-RAND_MAX)*T;
double w=get(x,y);
if(w<ans){
x_ans=x;
y_ans=y;
ans=w;
}
else if(exp((double)(ans-w)/T)>(double)rand()/RAND_MAX){
x_ans=x;
y_ans=y;
}
T*=delta;
}
}
signed main(){
ios::sync_with_stdio(false);
srand(seed);
cin>>n;
for(int i=1;i<=n;i++){
cin>>z[i].x>>z[i].y>>z[i].w;
x_ans+=z[i].w;
y_ans+=z[i].y;
}
x_ans/=n;
y_ans/=n;
ans=get(x_ans,y_ans);
// double timer=clock();
solve();
solve();
solve();
solve();
// solve();
printf("%.3lf %.3lf",x_ans,y_ans);
}
Luogu P2210
#include<bits/stdc++.h>
using namespace std;
int n;
int x,y,w;
int f[103][4];
int pos[1004];
const double T_min=1e-5;
const double delta=0.999;
int GET(){
int s=0;
for(int i=1;i<=n;i++){
for(int j=0;j<3;j++){
s+=abs(pos[i]-pos[f[i][j]]);
}
}
return s;
}
int ans;
void solve(){
double T=30000;
while(T>T_min){
x=rand()%n+1;
y=rand()%n+1;
// while(x==y) y=rand()%n+1;
swap(pos[x],pos[y]);
int k=GET();
if(ans>k){
ans=k;
}
else{
if(exp((double)(ans-k)/T)<=(double)rand()/INT_MAX){
swap(pos[x],pos[y]);
}
}
T*=delta;
}
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=0;j<3;j++){
cin>>f[i][j];
}
pos[i]=i;
}
ans=GET();
// cout<<ans<<endl;
int timer=clock();
while(clock()-timer<=CLOCKS_PER_SEC*0.98) solve();
cout<<ans/2;
}