Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- #define INF 1000010000
- #define nl '\n'
- #define pb push_back
- #define ppb pop_back
- #define mp make_pair
- #define fi first
- #define se second
- #define pii pair<int,int>
- #define pdd pair<double,double>
- #define all(c) (c).begin(), (c).end()
- #define SORT(c) sort(all(c))
- #define sz(c) (c).size()
- #define rep(i,n) for( int i = 0; i < n; ++i )
- #define repi(i,n) for( int i = 1 ; i <= n; ++i )
- #define repn(i,n) for( int i = n - 1 ; i >= 0 ; --i )
- #define repf(j,i,n) for( int j = i ; j < n ; ++j )
- #define die(s) {std::cout << s << nl;}
- #define dier(s) {std::cout << s; return 0;}
- #define vi vector<int>
- typedef long long ll;
- #define MAXN 55
- using namespace std;
- int n , m , k;
- vector<pii> life , magic;
- vi dx = {0 , 1 , 0 , -1};
- vi dy = {1 , 0 , -1 , 0};
- map<char , int> s;
- inline bool ok(pii p){
- int x = p.fi;
- int y = p.se;
- return x >= 0 && x < n && y >= 0 && y < m;
- }
- inline void fill(vector<vi> & v , pii a , pii b , char c){
- for(int i = min(a.fi , b.fi) ; i <= max(a.fi , b.fi) ; ++i){
- for(int j = min(a.se , b.se) ; j <= max(a.se , b.se) ; ++j){
- if(v[i][j] < 3 ){
- v[i][j] = c;
- ++s[c];
- }
- }
- }
- }
- inline void fill2(vector<vi> & v , map<pii , pii> & pr , pii a , pii b , char c){
- v[b.fi][b.se] = c;
- while(b != a){
- b = pr[b];
- v[b.fi][b.se] = c;
- ++s[c];
- }
- v[b.fi][b.se] = c;
- }
- void recalc_S(vector<vi> & v){
- s.clear();
- rep(i , n){
- rep(j , m){
- ++s[v[i][j]];
- }
- }
- }
- vector<vi> solve(const vector<pii> & life , const vector<pii> & magic){
- s.clear();
- vector<vi> v(MAXN , vi(MAXN , 0));
- queue<pii> q;
- rep(i , k){
- v[life[i].fi][life[i].se] = 1;
- v[magic[i].fi][magic[i].se] = 2;
- }
- vi index(k);
- rep(i , k){
- queue<pii> q;
- q.push({life[i]});
- index[i] = 'a' + i;
- v[life[i].fi][life[i].se] = 'a' + i;
- vector<vi> used(MAXN , vi(MAXN , 0));
- map<pii , pii> pr;
- used[life[i].fi][life[i].se] = 1;
- pr[life[i]] = {-1 , -1};
- while(sz(q)){
- pii cur = q.front();
- q.pop();
- if(v[cur.fi][cur.se] > 2 && v[cur.fi][cur.se] != 'a' + i){
- continue;
- }
- bool done = 0;
- rep(j , 4){
- pii nxt = {cur.fi + dx[j] , cur.se + dy[j]};
- if(ok(nxt) && v[nxt.fi][nxt.se] < 3 && !used[nxt.fi][nxt.se]){
- if(v[nxt.fi][nxt.se] == 2){
- pr[nxt] = cur;
- // fill(v , life[i] , nxt , 'a' + i);
- fill2(v , pr , life[i] , nxt , 'a' + i);
- done = 1;
- break;
- }else if(v[nxt.fi][nxt.se] == 0){
- pr[nxt] = cur;
- used[nxt.fi][nxt.se] = 1;
- q.push(nxt);
- }
- }
- }
- if(done){
- break;
- }
- }
- }
- recalc_S(v);
- return v;
- }
- vector<vi> solve2(const vector<pii> & life , const vector<pii> & magic){
- s.clear();
- vector<vi> v(MAXN , vi(MAXN , 0));
- queue<pii> q;
- rep(i , k){
- v[life[i].fi][life[i].se] = 1;
- v[magic[i].fi][magic[i].se] = 2;
- }
- vi index(k);
- rep(i , k){
- queue<pii> q;
- q.push({life[i]});
- index[i] = 'a' + i;
- v[life[i].fi][life[i].se] = 'a' + i;
- vector<vi> used(MAXN , vi(MAXN , 0));
- map<pii , pii> pr;
- used[life[i].fi][life[i].se] = 1;
- pr[life[i]] = {-1 , -1};
- while(sz(q)){
- pii cur = q.front();
- q.pop();
- if(v[cur.fi][cur.se] > 2 && v[cur.fi][cur.se] != 'a' + i){
- continue;
- }
- bool done = 0;
- rep(j , 4){
- pii nxt = {cur.fi + dx[j] , cur.se + dy[j]};
- if(ok(nxt) && v[nxt.fi][nxt.se] < 3 && !used[nxt.fi][nxt.se]){
- if(v[nxt.fi][nxt.se] == 2){
- pr[nxt] = cur;
- fill(v , life[i] , nxt , 'a' + i);
- done = 1;
- break;
- }else if(v[nxt.fi][nxt.se] == 0){
- pr[nxt] = cur;
- used[nxt.fi][nxt.se] = 1;
- q.push(nxt);
- }
- }
- }
- if(done){
- break;
- }
- }
- }
- recalc_S(v);
- return v;
- }
- vector<vi> solve3(vector<pii> life){
- vector<vi> v(MAXN , vi(MAXN , 0));
- rep(i , k){
- v[life[i].fi][life[i].se] = 1;
- v[magic[i].fi][magic[i].se] = 2;
- }
- int w = 0;
- repf(a , 1 , min(7 , n + 1)){
- repf(b , 1 , min(7 , m + 1)){
- if(a == 1 && b == 1)continue;
- rep(i , n - a + 1){
- rep(j , m - b + 1){
- int cnt1 = 0 , cnt2 = 0;
- pii so = {0 , 0};
- pii ta = {0 , 0};
- rep(x , a){
- rep(y , b){
- if(v[x + i][y + j] == 1){
- ++cnt1;
- so = {x + i , y + j};
- }else if(v[x + i][y + j] == 2){
- ++cnt2;
- ta = {x + i , y + j};
- }
- }
- }
- if(cnt1 == 1 && cnt2 == 1){
- bool ck = 0;
- queue<pii> q;
- vector<vi> used(n , vi(m , 0));
- used[so.fi][so.se] = 1;
- q.push(so);
- while(sz(q)){
- pii cur = q.front();
- q.pop();
- bool done = 0;
- rep(i , 4){
- pii nxt = {cur.fi + dx[i] , cur.se + dy[i]};
- if(ok(nxt)){
- if(nxt.fi >= i && nxt.fi < i + a && nxt.se >= j && nxt.se < j + b){
- if(!used[nxt.fi][nxt.se] && v[nxt.fi][nxt.se] < 3){
- if(nxt == ta){
- done = 1;
- ck = 1;
- break;
- }
- used[nxt.fi][nxt.se] = 1;
- q.push(nxt);
- }
- }
- }
- }
- if(done)break;
- }
- if(ck){
- rep(x , a){
- rep(y , b){
- if(v[x + i][y + j] < 3){
- v[x + i][y + j] = w + 'a';
- }
- }
- }
- ++w;
- }
- if(w == k){
- recalc_S(v);
- return v;
- }
- }
- }
- }
- }
- }
- return v;
- }
- void finalize(vector<vi> & v){
- bool rec = 0;
- rep(i , n){
- rep(j , m){
- if(v[i][j] == 0){
- vector<pii> ck;
- rep(l , 4){
- pii cur = {i + dx[l] , j + dy[l]};
- if(ok(cur) && v[cur.fi][cur.se] != 0){
- ck.pb({s[v[cur.fi][cur.se]] , v[cur.fi][cur.se]});
- }
- }
- SORT(ck);
- if(!sz(ck)){
- rec = 1;
- continue;
- }
- // reverse(all(ck));
- v[i][j] = ck[0].se;
- ++s[ck[0].se];
- }
- }
- }
- if(rec){
- finalize(v);
- }
- }
- bool checker(vector<vi> & v , const vector<pii> & life , const vector<pii> & magic){
- vector<vi> t(MAXN , vi(MAXN , 0));
- rep(i , k){
- t[life[i].fi][life[i].se] = 1;
- t[magic[i].fi][magic[i].se] = 2;
- }
- rep(l , k){
- int cur = 'a' + l;
- int source = 0;
- int target = 0;
- pii so , ta;
- int cnt = 0;
- rep(i , n){
- rep(j , m){
- if(v[i][j] == cur){
- ++cnt;
- if(t[i][j] == 2){
- if(!target){
- ++target;
- ta = {i , j};
- }else{
- return 0;
- }
- }
- if(t[i][j] == 1){
- if(!source){
- ++source;
- so = {i , j};
- }else{
- return 0;
- }
- }
- }
- }
- }
- if(target != 1 || source != 1)return 0;
- vector<vi> used(MAXN , vi(MAXN , 0));
- used[so.fi][so.se] = 1;
- queue<pii> q;
- q.push(so);
- while(sz(q)){
- pii c = q.front();
- q.pop();
- if(v[c.fi][c.se] == cur){
- --cnt;
- }
- rep(i , 4){
- pii nxt = {c.fi + dx[i] , c.se + dy[i]};
- if(ok(nxt) && !used[nxt.fi][nxt.se] && v[nxt.fi][nxt.se] == cur){
- used[nxt.fi][nxt.se] = 1;
- q.push(nxt);
- }
- }
- }
- if(cnt)return 0;
- }
- return 1;
- }
- inline pii get_next(vector<vi> & v , pii a){
- rep(i , 4){
- pii b = {a.fi + dx[i] , a.se + dy[i]};
- if(ok(b) && v[b.fi][b.se] == v[a.fi][a.se]){
- return b;
- }
- }
- return {a.fi + dx[0] , a.se + dy[0]};
- }
- inline pii get_first(vector<vi> & v , int cur){
- rep(i , n){
- rep(j , m){
- if(v[i][j] == cur){
- return {i , j};
- }
- }
- }
- return {0 , 0};
- }
- int P(vector<vi> & v , int cur){
- int p = 0;
- rep(j , m){
- rep(i , n){
- pii next = {i + 1 , j};
- pii prev = {i - 1 , j};
- if(ok(next) && v[i][j] == cur && v[i + 1][j] != cur){
- ++p;
- }
- if(ok(prev) && v[i][j] == cur && v[i - 1][j] != cur){
- ++p;
- }
- if(!ok(next) && v[i][j] == cur){
- ++p;
- }
- if(!ok(prev) && v[i][j] == cur){
- ++p;
- }
- }
- }
- rep(i , n){
- rep(j , m){
- pii next = {i , j + 1};
- pii prev = {i , j - 1};
- if(ok(next) && v[i][j] == cur && v[i][j + 1] != cur){
- ++p;
- }
- if(ok(prev) && v[i][j] == cur && v[i][j - 1] != cur){
- ++p;
- }
- if(!ok(next) && v[i][j] == cur){
- ++p;
- }
- if(!ok(prev) && v[i][j] == cur){
- ++p;
- }
- }
- }
- return p;
- }
- int drop_p(vector<vi> & v , int x , int y , int p){
- int bias = 0;
- rep(i , 4){
- int xx = x + dx[i];
- int yy = y + dy[i];
- if(ok({xx , yy})){
- if(v[xx][yy] == v[x][y]){
- ++bias;
- }else{
- --bias;
- }
- }else{
- --bias;
- }
- }
- return p + bias;
- }
- int add_p(vector<vi> & v , int x , int y , int p){
- int bias = 0;
- rep(i , 4){
- int xx = x + dx[i];
- int yy = y + dy[i];
- if(ok({xx , yy})){
- if(v[xx][yy] == v[x][y]){
- ++bias;
- }else{
- --bias;
- }
- }else{
- --bias;
- }
- }
- return p - bias;
- }
- void swapper(vector<vi> & v , const vector<pii> & life , const vector<pii> & magic){
- vector<vi> need(MAXN , vi(MAXN , 0));
- rep(i , k){
- need[life[i].fi][life[i].se] = 1;
- need[magic[i].fi][magic[i].se] = 2;
- }
- rep(i , k){
- queue<pii> q;
- vector<vi> used(MAXN , vi(MAXN , 0));
- int pr[MAXN][MAXN][2];
- used[life[i].fi][life[i].se] = 1;
- q.push(life[i]);
- rep(x , n)
- rep(y , m)
- pr[x][y][0] = pr[x][y][1] = 0;
- pii ta = {0 , 0};
- while(sz(q)){
- pii cur = q.front();
- q.pop();
- bool done = 0;
- rep(j , 4){
- pii nxt = {cur.fi + dx[j] , cur.se + dy[j]};
- if(ok(nxt) && !used[nxt.fi][nxt.se] && v[nxt.fi][nxt.se] == v[life[i].fi][life[i].se]){
- pr[nxt.fi][nxt.se][0] = cur.fi;
- pr[nxt.fi][nxt.se][1] = cur.se;
- used[nxt.fi][nxt.se] = 1;
- if(need[nxt.fi][nxt.se] == 2){
- ta = nxt;
- done = 1;
- break;
- }
- q.push(nxt);
- }
- }
- if(done)break;
- }
- need[ta.fi][ta.se] = 1;
- while(ta != life[i]){
- int x = pr[ta.fi][ta.se][0];
- int y = pr[ta.fi][ta.se][1];
- ta = {x , y};
- need[ta.fi][ta.se] = 1;
- }
- need[ta.fi][ta.se] = 1;
- }
- /*
- rep(i , n){
- rep(j , m){
- cout << need[i][j];
- }
- cout << nl;
- }*/
- map<int , int> p;
- rep(i , k){
- p['a' + i] = P(v , 'a' + i);
- }
- rep(i , n){
- rep(j , m){
- if(!need[i][j]){
- int best = v[i][j];
- int best_p = p[best];
- int best_s = s[best];
- int r_p = drop_p(v , i , j , best_p);
- int r_s = best_s - 1;
- rep(l , 4){
- int x = i + dx[l];
- int y = j + dy[l];
- if(ok({x , y})){
- int cur = v[x][y];
- if(cur != best){
- int cur_p = p[cur];//P(v , cur);
- int cur_s = s[cur];
- // v[i][j] = cur;
- int ck_p = add_p(v , x , y , cur_p);
- int ck_s = cur_s + 1;
- // v[i][j] = best;
- // cout << ck_p << " " << add_p(v , x , y , cur_p) << nl;
- double d1 = ((double)best_s / (double)(best_p * best_p)) +
- ((double)cur_s / (double)(cur_p * cur_p));
- double d2 = ((double)r_s / (double)(r_p * r_p)) +
- ((double)ck_s / (double)(ck_p * ck_p));
- if(d2 > d1){
- p[cur] = ck_p;
- p[best] = r_p;
- s[cur] = ck_s;
- s[best] = ck_s;
- best = cur;
- best_p = ck_p;
- best_s = ck_s;
- r_p = cur_p;
- r_s = cur_s;
- v[i][j] = best;
- }
- }
- }
- }
- // cout << (char)best << " " << best_p << " " << best_s << nl;
- }
- }
- }
- }
- double sum(vector<vi> & v , const vector<pii> & life , const vector<pii> & magic , bool flag = 0){
- recalc_S(v);
- if(flag){
- rep(i , n){
- rep(j , m){
- cout << (char)v[i][j] ;
- }
- cout << nl;
- }
- }
- double res = 0;
- rep(l , k){
- int cur = 'a' + l;
- int p = P(v , cur);
- int S = s[cur];
- if(flag)cout << (char)cur << " " << S << nl;
- res += (double)S / (double)(p * p);
- }
- return res;
- }
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(NULL);
- // cout.precision(10);
- // cout.setf(ios::fixed);
- cin >> n >> m >> k;
- life.resize(k);
- magic.resize(k);
- rep(i , k){
- cin >> life[i].fi >> life[i].se;
- }
- rep(i , k){
- cin >> magic[i].fi >> magic[i].se;
- }
- /*
- struct{
- bool operator()(pii & a , pii & b){
- int d1 = INF , d2 = INF;
- rep(i , k){
- d1 = min(d1 , abs(a.fi - magic[i].fi) + abs(a.se - magic[i].se));
- d2 = min(d2 , abs(b.fi - magic[i].fi) + abs(b.se - magic[i].se));
- }
- return d1 < d2;
- }
- }comp;
- sort(all(life) , comp);*/
- auto v2 = solve3(life);
- finalize(v2);
- auto v1 = solve(life , magic);
- finalize(v1);
- ll start = clock();
- vector<vi> best = v1;
- double best_res = -INF;
- if(checker(v1 , life , magic)){
- best_res = sum(v1 , life , magic);
- }
- if(checker(v2 , life , magic)){
- double d = sum(v2 , life , magic);
- if(d > best_res){
- best_res = d;
- best = v2;
- }
- }
- rep(kk , 5){
- random_shuffle(all(life));
- random_shuffle(all(magic));
- v1 = solve(life , magic);
- finalize(v1);
- if(checker(v1 , life , magic)){
- double d = sum(v1 , life , magic);
- if(d > best_res){
- best_res = d;
- best = v1;
- }
- }
- v1 = solve2(life , magic);
- finalize(v1);
- //if(k < 5 && kk < 5)
- // swapper(v1 , life , magic);
- if(checker(v1 , life , magic)){
- double d = sum(v1 , life , magic);
- if(d > best_res){
- best_res = d;
- best = v1;
- }
- }
- }
- v1 = best;
- /* if(checker(v1 , life , magic) == 0){
- do{
- random_shuffle(all(life));
- random_shuffle(all(magic));
- v1 = solve(life , magic);
- finalize(v1);
- }while(checker(v1 , life , magic) == 0);
- best = v1;
- }*/
- // cout << start << " " << clock() << " " << clock() - start << nl;
- while(clock() - start < 1500000){
- // cout << "hi\n";
- random_shuffle(all(life));
- random_shuffle(all(magic));
- v1 = solve(life , magic);
- finalize(v1);
- if(checker(v1 , life , magic)){
- double d = sum(v1 , life , magic);
- if(d > best_res){
- best_res = d;
- best = v1;
- }
- }
- v1 = solve2(life , magic);
- finalize(v1);
- if(checker(v1 , life , magic)){
- double d = sum(v1 , life , magic);
- if(d > best_res){
- best_res = d;
- best = v1;
- }
- }
- }
- v2 = best;
- swapper(v2 , life , magic);
- if(checker(v2 , life , magic)){
- if(sum(v2, life , magic) > best_res)best = v2;
- // swapper(v2 , life , magic);
- }
- rep(i , n){
- rep(j , m){
- cout << (char)best[i][j];
- }
- cout << nl;
- }
- // sum(best , life , magic , 1);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement