- 装箱问题
- 2025-04-10 01:30:02 @
发现如果本题数据大了就会TLE 肯定是样例 water 了
我第一遍写了一下
#include <bits/stdc++.h>
using namespace std;
int v, n;
vector<int> volumes;
int best_remain;
double T = 1e5;
double T_min = 1e-8;
double alpha = 0.995;
int steps = 3000;
random_device rd;
mt19937 gen(rd());
uniform_real_distribution<> prob(0.0, 1.0);
int main() {
cin >> v >> n;
volumes.resize(n);
for (int i = 0; i < n; ++i) {
cin >> volumes[i];
}
vector<bool> selected(n, false);
int current_sum = 0;
best_remain = v;
int current_E = v;
uniform_int_distribution<> idx_dist(0, n-1);
while (T > T_min) {
for (int i = 0; i < steps; ++i) {
int idx = idx_dist(gen);
bool was_selected = selected[idx];
int new_sum = current_sum + (was_selected ? -volumes[idx] : volumes[idx]);
int E_new;
if (new_sum > v) {
E_new = (new_sum - v) * 100000;
} else {
E_new = v - new_sum;
}
if (new_sum <= v) {
int remain = v - new_sum;
if (remain < best_remain) {
best_remain = remain;
if (best_remain == 0) {
cout << 0 << endl;
return 0;
}
}
}
int delta = E_new - current_E;
if (delta < 0 || prob(gen) < exp(-delta / T)) {
current_sum = new_sum;
selected[idx] = was_selected;
current_E = E_new;
}
}
T *= alpha;
}
cout << best_remain << endl;
return 0;
}
发现炸了,经过我11514遍检查
原来是少写一个 !
我胳膊瞎了
退火 AC 代码
```cpp
#include <bits/stdc++.h>
using namespace std;
int v, n;
vector<int> volumes;
int best_remain;
double T = 1e5;
double T_min = 1e-8;
double alpha = 0.995;
int steps = 3000;
random_device rd;
mt19937 gen(rd());
uniform_real_distribution<> prob(0.0, 1.0);
int main() {
cin >> v >> n;
volumes.resize(n);
for (int i = 0; i < n; ++i) {
cin >> volumes[i];
}
vector<bool> selected(n, false);
int current_sum = 0;
best_remain = v;
int current_E = v;
uniform_int_distribution<> idx_dist(0, n-1);
while (T > T_min) {
for (int i = 0; i < steps; ++i) {
int idx = idx_dist(gen);
bool was_selected = selected[idx];
int new_sum = current_sum + (was_selected ? -volumes[idx] : volumes[idx]);
int E_new;
if (new_sum > v) {
E_new = (new_sum - v) * 100000;
} else {
E_new = v - new_sum;
}
if (new_sum <= v) {
int remain = v - new_sum;
if (remain < best_remain) {
best_remain = remain;
if (best_remain == 0) {
cout << 0 << endl;
return 0;
}
}
}
int delta = E_new - current_E;
if (delta < 0 || prob(gen) < exp(-delta / T)) {
current_sum = new_sum;
selected[idx] = !was_selected; //here!!!!!!!!!!!!!!111
current_E = E_new;
}
}
T *= alpha;
}
cout << best_remain << endl;
return 0;
}
```
1 条评论
-
202502gj01花子轩 (EL230810) LV 8 @ 2025-04-26 11:19:58
这份代码是可以卡掉的
20000 30 19999 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
加贪心初始化就行了(最好是用dp,不然容易hack,退火毕竟还是启发式搜索)
- 1