发现如果本题数据大了就会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 条评论

  • 这份代码是可以卡掉的

    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

信息

ID
1437
难度
6
分类
动态规划 | 背包 点击显示
标签
递交数
127
已通过
31
通过率
24%
上传者