#include using namespace std; using ll = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, U; if(!(cin >> N >> U)) return 0; int H, W; cin >> H >> W; int HW = H * W; vector F(N); vector S(N, string()); for(int i=0;i> F[i]; string grid; grid.reserve(HW); for(int r=0;r> row; grid += row; } S[i] = grid; } // weights: 1-based i <= U gives +1, else -1 vector wt(N); for(int i=0;i& d)->int{ int s=0; for(int i=0;i= N ? '#' : '.'); } // compute initial d vector d(N,0); for(int i=0;i best_d = d; int best_score = cur_score; // RNG std::mt19937_64 rng((unsigned)chrono::high_resolution_clock::now().time_since_epoch().count()); uniform_real_distribution unif01(0.0, 1.0); uniform_int_distribution pos_dist(0, HW-1); // parameters (tweakable) const double TIME_LIMIT = 1.8; // seconds (adjust if needed) const double T0 = 1.0; // initial temperature const double TEND = 1e-4; // final temperature const int RESTARTS = 6; // number of restarts (including majority-start) const int MAX_NO_IMPROVE_ITER = 2000; auto now = chrono::high_resolution_clock::now; auto start_time = now(); // perform multiple runs (first run is majority initial, others random perturbations) for(int run = 0; run < RESTARTS; ++run){ // if time is nearly over, break double elapsed = chrono::duration(now() - start_time).count(); if(elapsed > TIME_LIMIT) break; // for runs > 0, create a perturbed initial state (random flips) if(run > 0){ // start from majority then flip some random positions g = best_g; int flips = max(1, HW/10); for(int t=0;t(now() - start_time).count(); if(t_elapsed > TIME_LIMIT) break; // linear/exponential schedule based on elapsed fraction double frac = t_elapsed / TIME_LIMIT; if(frac > 1.0) frac = 1.0; // exponential cooling T = T0 * pow(TEND / T0, frac); // pick random position to flip int p = pos_dist(rng); // compute delta score if we flip p int delta = 0; for(int i=0;i flipping makes unequal (+1), otherwise -1 bool old_ok = (old_d <= F[i]); bool new_ok = (new_d <= F[i]); if(old_ok != new_ok){ if(new_ok) delta += wt[i]; else delta -= wt[i]; } } bool accept = false; if(delta > 0) accept = true; else { double prob = exp((double)delta / max(1e-12, T)); // delta<=0 so prob<=1 double r = unif01(rng); if(r < prob) accept = true; } if(accept){ // apply flip for(int i=0;i best_score){ best_score = cur_score; best_g = g; best_d = d; no_improve = 0; } else { no_improve++; } } else { no_improve++; } // exit if too long without improvement if(no_improve > MAX_NO_IMPROVE_ITER) break; } // end while SA loop // time check double elapsed_after_run = chrono::duration(now() - start_time).count(); if(elapsed_after_run > TIME_LIMIT) break; } // end runs // final output cout << best_score << "\n"; for(int r=0;r