CF1239E Turtle
直接退火會被後三個點卡,好像數都是二的次冪,卡的原理未知。
發現性質:當第一行放哪些數第二行放哪些數確定時,第一行從小到大排序,第二行從大到小排序,一定是最優的。
https://codeforces.com/contest/1239/submission/216230291
用 nmw 的號交的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<random>
#include<ctime>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 30, M = 60;
int n, a[3][N];
int f[3][N];
int b[3][N], c[3][N];
int tp[M];
int ga(){
sort(b[1]+1, b[1]+n+1);
sort(b[2]+1, b[2]+n+1, greater<int>());
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
f[i][j] = max(f[i-1][j], f[i][j-1]) + b[i][j];
}
}
return f[2][n];
}
mt19937 mrd(time(NULL));
int rd(int x, int y){
return mrd()%(y-x+1)+x;
}
int zans, ans, tans;
void SA(){
for(double T = 5000000; T >= 1e-13; T *= 0.999995){
int x = rd(1, n), y = rd(1, n);
swap(b[1][x], b[2][y]);
tans = ga();
if(tans < ans){
ans = tans;
if(tans < zans){
zans = tans;
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
c[i][j] = b[i][j];
}
}
}
}else{
if(exp((ans-tans)/T) >= (double)rand()/RAND_MAX){
ans = tans;
}else{
swap(b[1][x], b[2][y]);
}
}
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
scanf("%d", &a[i][j]);
tp[(i-1)*n+j] = a[i][j];
}
}
shuffle(tp+1, tp+1+2*n, mrd);
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
b[i][j] = tp[(i-1)*n+j];
}
}
ans = ga();
zans = ans;
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
c[i][j] = b[i][j];
}
}
SA();
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
printf("%d ", c[i][j]);
}
puts("");
}
return 0;
}
CF730I
直接退火最高成績是 Wrong answer on test 89。
https://codeforces.com/contest/730/submission/216227556