1815. 得到新鲜甜甜圈的最多组数 - 力扣(LeetCode)
class Solution {
public:
int batchSize;
int n;
int ans = 0;
vector<int> groups;
int energy()
{
int res = 1;
for (int i = 0, s = 0; i < n; i ++ ) {//计算是否有剩余
s = (s + groups[i]) % batchSize;
if (!s && i < n - 1) res ++ ;
}
ans = max(ans, res);
return -res;
}
void th()
{
srand(time(NULL));//很重要
random_shuffle(groups.begin(), groups.end());
for(double t = 1e6; t > 1e-6; t *= 0.96)
{
int a = rand() % n, b = rand() % n;
int ea = energy();
swap(groups[a], groups[b]);
int eb = energy();
int dt = eb - ea;
if(exp(-dt / t) > (double)rand() / RAND_MAX) continue;
swap(groups[a], groups[b]);
}
}
int maxHappyGroups(int _batchSize, vector<int>& _groups) {
//调整groups的顺序,使最多人开心
batchSize = _batchSize;
groups = _groups;
n = groups.size();
for(int i = 0; i < 40; i ++ )
th();
return ans;
}
};
1723. 完成所有工作的最短时间 - 力扣(LeetCode)
class Solution {
public:
int ans = INT_MAX;
vector<int> jobs;
int energy(int k)
{
int n = jobs.size();
vector<int> s(k);
for(int i = 0; i < n; i ++ )//对于每项工作,找到一个最闲的工人分配
{
int kk = 0;
for(int j = 1; j < k; j ++ )
if(s[j] < s[kk]) kk = j;
s[kk] += jobs[i];
}
int res = 0;
for(auto &x : s)
res = max(x, res);//找到最大工作时间
ans = min(ans, res);
return res; //能量越小越好
}
void th(int k)
{
int n = jobs.size();
double T = 10000;//一个很高的温度
random_shuffle(jobs.begin(), jobs.end());//产生随机的工作分配顺序
while(T > 1e-4) //降温过程
{
T *= 0.92;
int a = rand() % n, b = rand() % n;
int ea = energy(k);
swap(jobs[a], jobs[b]);
int eb = energy(k);
int dt = eb - ea;
if(dt <= 0 || exp(-dt / T) > rand() / RAND_MAX) continue;//以一定概率接受
swap(jobs[a], jobs[b]);//不接受
}
}
int minimumTimeRequired(vector<int>& _jobs, int k) {
//每个工人至少分配一个工作
jobs = _jobs;
for(int i = 0; i < 7; i ++ )
th(k);
return ans;
}
};
1879. 两个数组最小的异或值之和 - 力扣(LeetCode)
class Solution {
public:
vector<int> nums1, nums2;
int n;
int ans = INT_MAX;
int energy()
{
int res = 0;
for(int i = 0; i < n; i ++ )
res += nums1[i] ^ nums2[i];
ans = min(ans, res);
return res;//越小越好
}
void th()
{
srand(time(NULL));
random_shuffle(nums1.begin(), nums1.end());
for(double t = 1e6; t > 1e-5; t *= 0.99)
{
int a = rand() % n, b = rand() % n;
int ea = energy();
swap(nums2[a], nums2[b]);
int eb = energy();
int dt = eb - ea;
if(dt < 0) continue;
if(exp(-dt / t) > (double)rand() / RAND_MAX) continue; //恶化了,恶化的越大,越要回去
swap(nums2[a], nums2[b]);
}
}
int minimumXORSum(vector<int>& _nums1, vector<int>& _nums2) {
nums1 = _nums1;
nums2 = _nums2;
n = nums2.size();
for(int i = 0; i < 10; i ++ )
th();
return ans;
}
};
1655. 分配重复整数 - 力扣(LeetCode)
class Solution {
public:
vector<int> nums;
vector<int> quantity;
int n;
int ans = 0;
int m;
int energy()
{
vector<int> tmp = nums;
int res = 0;
for(int i = 0; i < m; i ++ )// 对于每个人
{
int flag = false;
for(int j = 0; j < n; j ++ )//找到第一个可以拿的数字
{
if(tmp[j] >= quantity[i])
{
flag = true;
tmp[j] -= quantity[i];
break;
}
}
if(flag) res ++;
}
ans = max(ans, res);
return res;//能量大的好
}
void th()
{
srand(time(NULL));
random_shuffle(nums.begin(), nums.end());
for(double t = 1e5; t > 1e-5; t *= 0.95)
{
int a = rand() % n, b = rand() % n;
int ea = energy();
swap(nums[a], nums[b]);
int eb = energy();
int dt = ea - eb;
if(dt < 0) continue;
if(exp(-1 * dt / t) > rand() / RAND_MAX) continue;
swap(nums[a], nums[b]);
}
}
bool canDistribute(vector<int>& _nums, vector<int>& _quantity) {
//分配相同整数
vector<int> mp(1001);
quantity = _quantity;
sort(quantity.begin(), quantity.end(), greater<int>());//从大到小排序, 非常关键,为了尽可能的增加全部都分配好的概率,先解决数量大的
m = quantity.size();
for(auto x: _nums)
mp[x] ++;
for(int i = 1; i <= 1000; i ++ )
{
if(mp[i])
nums.push_back(mp[i]);
}
n = nums.size();
for(int i = 0; i < 5; i ++ )
th();
return ans == m;
}
};
1515. 服务中心的最佳位置 - 力扣(LeetCode)
class Solution {
public:
double sum(double x, double y, vector<vector<int>>& positions) {
int n = positions.size();
double ans = 0;
for (int i = 0; i < n; i++) {
ans += sqrt(pow(x - positions[i][0], 2) + pow(y - positions[i][1], 2));
}
return ans;
}
double getMinDistSum(vector<vector<int>>& positions) {
int n = positions.size();
double step = 100;
double x = positions[0][0];
double y = positions[0][1];
while (step > 1e-7) {
bool flag = true;
double rad = rand() % 360;
while(flag)
{
flag = false;
double nx = x + step * cos(rad);
double ny = y + step * sin(rad);
if (sum(nx, ny, positions) < sum(x, y, positions))
{
x = nx;
y = ny;
flag = true;
}
}
step *= 0.85;
}
return sum(x, y, positions);
}
};
爬山法
class Solution {
private:
static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public:
double getMinDistSum(vector<vector<int>>& positions) {
double eps = 1e-7;
double step = 1;
double decay = 0.5;
int n = positions.size();
double x = 0.0, y = 0.0;
for (const auto& pos: positions) {
x += pos[0];
y += pos[1];
}
x /= n;
y /= n;
// 计算服务中心 (xc, yc) 到客户的欧几里得距离之和
auto getDist = [&](double xc, double yc) {
double ans = 0;
for (const auto& pos: positions) {
ans += sqrt((pos[0] - xc) * (pos[0] - xc) + (pos[1] - yc) * (pos[1] - yc));
}
return ans;
};
while (step > eps) {
bool modified = false;
for (int i = 0; i < 4; ++i) {
double xNext = x + step * dirs[i][0];
double yNext = y + step * dirs[i][1];
if (getDist(xNext, yNext) < getDist(x, y)) {
x = xNext;
y = yNext;
modified = true;
break;
}
}
if (!modified) {
step *= (1.0 - decay);
}
}
return getDist(x, y);
}
};
1239. 串联字符串的最大长度 - 力扣(LeetCode)
class Solution {
public:
vector<string> arr;
int n;
int ans = 0;
bool book[27];
int enengy()
{
int res = 0;
memset(book, 0, sizeof book);
for(int i = 0; i < n; i ++ )
{
int flag = true;
for(auto c: arr[i])
{
if(book[c - 'a'])
{
flag = false;
break;
};
book[c - 'a'] = true;
}
if(flag) res += arr[i].size();
}
return res;
}
void th()
{
srand(time(NULL));
random_shuffle(arr.begin(), arr.end());
for(int t = 1e6; t > 1e-6; t *= 0.96)
{
int a = rand() % n, b = rand() % n;
int ea = enengy();
swap(arr[a], arr[b]);
int eb = enengy();
ans = max({ans, ea, eb});
int dt = ea - eb;
if(dt < 0) continue;
if(exp(-1 * dt / t) >= rand() / RAND_MAX) continue;
swap(arr[a], arr[b]);
}
}
int maxLength(vector<string>& _arr) {
for(auto s: _arr)
{
memset(book, 0, sizeof book);
bool flag = true;
for(auto c: s)
{
if(book[c - 'a'])
{
flag = false;
break;
}
book[c - 'a'] = true;
}
if(flag) arr.push_back(s);
}
n = arr.size();
if(!n) return 0;
for(int i = 0; i < 2; i ++ )
th();
return ans;
}
};