AquaBlitz11

Untitled

Apr 4th, 2020
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.45 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N = 55;
  5. using pii = pair<int, int>;
  6.  
  7. default_random_engine RNG(31415926);
  8.  
  9. int main()
  10. {
  11.     int T;
  12.     scanf("%d", &T);
  13.     for (int t = 1; t <= T; ++t) {
  14.  
  15.         int n, k;
  16.         scanf("%d%d", &n, &k);
  17.         int ok = k;
  18.         bool flip = false;
  19.         if (n*(n+1)-k < k) {
  20.             k = n*(n+1)-k;
  21.             flip = true;
  22.         }
  23.  
  24.         int val[N] = {}, sum;
  25.  
  26.         if (k == n+1 || k == n*n-1 || (n == 3 && !(k == 3 || k == 6 || k == 9))) {
  27.             printf("Case #%d: IMPOSSIBLE\n", t);
  28.             continue;
  29.         } else if (k%n == 0) {
  30.             fill(val, val+n, k/n);
  31.             sum = k;
  32.         } else if (k%n == 1) {
  33.             fill(val, val+n, k/n);
  34.             ++val[0];
  35.             ++val[1];
  36.             --val[2];
  37.             sum = k;
  38.         } else if (k%n == n-1) {
  39.             fill(val, val+n, (k+1)/n);
  40.             ++val[0];
  41.             --val[1];
  42.             --val[2];
  43.             sum = k;
  44.         } else {
  45.             fill(val, val+n, k/n);
  46.             ++val[0], ++val[1];
  47.             sum = (k/n)*n+2;
  48.             for (int i = 0; i < n && sum < k; ++i) {
  49.                 while (sum < k && ((i < n-2 && val[i] < n)
  50.                 || (i >= n-2 && val[i] < n-1)))
  51.                     ++val[i], ++sum;
  52.             }
  53.         }
  54.  
  55.         if (flip) {
  56.             k = ok;
  57.             for (int i = 0; i < n; ++i)
  58.                 val[i] = (n+1) - val[i];
  59.         }
  60.  
  61.         /*for (int i = 0; i < n; ++i)
  62.             printf("%d ", val[i]);
  63.         printf("\n");*/
  64.         pii cnt[N];
  65.         for (int i = 1; i <= n; ++i)
  66.             cnt[i] = pii(0, i);
  67.         for (int i = 0; i < n; ++i)
  68.             ++cnt[val[i]].first;
  69.         sort(cnt+1, cnt+n+1, greater<pii>());
  70.  
  71.         int arr[N][N] = {}, ori[N][N] = {}; // 1-based index
  72.         bool row[N][N] = {}, col[N][N] = {};
  73.         bool orirow[N][N] = {}, oricol[N][N] = {};
  74.         sum = 0; // now tracking the position
  75.         for (int i = 1; i <= n; ++i) {
  76.             for (int j = 0; j < cnt[i].first; ++j) {
  77.                 ++sum;
  78.                 ori[sum][sum] = arr[sum][sum] = i;
  79.                 orirow[sum][i] = row[sum][i] = true;
  80.                 oricol[sum][i] = col[sum][i] = true;
  81.             }
  82.         }
  83.  
  84.         int last = 0;
  85.         for (int i = 2; i <= n; ++i)
  86.             last += cnt[i].first;
  87.         int rev[N] = {};
  88.         for (int i = 1; i <= n; ++i)
  89.             rev[i] = cnt[i].second;
  90.  
  91.         /*for (int i = 1; i <= n; ++i)
  92.             printf("%d %d\n", cnt[i].first, cnt[i].second);*/
  93.  
  94.         auto greedy = [&] (int num, int start) {
  95.             int order[N] = {}, where=0;
  96.             for (int i = start; i <= n; ++i)
  97.                 order[where++] = i;
  98.             for (int i = 1; i <= start-1; ++i)
  99.                 order[where++] = i;
  100.  
  101.             for (int i = 1; i <= n; ++i) {
  102.                 if (row[i][num]) continue;
  103.                 bool ok = false;
  104.                 for (int x = 0; x < n; ++x) {
  105.                     int j = order[x];
  106.                     if (!arr[i][j] && !col[j][num]) {
  107.                         arr[i][j] = num;
  108.                         row[i][num] = col[j][num] = true;
  109.                         ok = true;
  110.                         break;
  111.                     }
  112.                 }
  113.                 if (ok) continue;
  114.                 return false;
  115.             }
  116.             return true;
  117.         };
  118.  
  119.         auto dogreedy = [&] (const vector<int> &ord) {
  120.             for (int i = 1; i <= n; ++i) {
  121.                 for (int j = 1; j <= n; ++j) {
  122.                     arr[i][j] = ori[i][j];
  123.                     row[i][j] = orirow[i][j];
  124.                     col[i][j] = oricol[i][j];
  125.                 }
  126.             }
  127.             for (auto x : ord) {
  128.                 if (!greedy(x, x))
  129.                     return false;
  130.             }
  131.             return true;
  132.         };
  133.  
  134.         vector<int> ord1, ord2;
  135.         for (int i = 1; i <= n; ++i) {
  136.             ord1.push_back(i);
  137.             if (i == 1) ord2.push_back(n);
  138.             if (i > 1 && i < n) ord2.push_back(i);
  139.             ord2.push_back(1);
  140.         }
  141.         bool pass = true;
  142.         if (!dogreedy(ord1)) {
  143.             if (!dogreedy(ord2)) {
  144.                 bool ok = false;
  145.                 int cntperm = 0;
  146.                 do {
  147.                     ++cntperm;
  148.                     shuffle(ord1.begin(), ord1.end(), RNG);
  149.                     if (dogreedy(ord1)) {
  150.                         fprintf(stderr, "Case %d: %d\n", t, cntperm);
  151.                         //for (int i = 1; i <= n; ++i)
  152.                             //fprintf(stderr, "%d %d\n", cnt[i].first, cnt[i].second);
  153.                         ok = true;
  154.                         break;
  155.                     }
  156.                 } while (cntperm < 10000);
  157.                 //} while (next_permutation(ord1.begin(), ord1.end()));
  158.                 if (!ok) pass = false;
  159.             }
  160.         }
  161.  
  162.         if (!pass) {
  163.             fprintf(stderr, "FAIL ON CASE %d\n", t);
  164.             for (int i = 1; i <= n; ++i)
  165.                 fprintf(stderr, "%d %d\n", cnt[i].first, cnt[i].second);
  166.             exit(1);
  167.         }
  168.  
  169.         printf("Case #%d: POSSIBLE", t);
  170.         for (int i = 1; i <= n; ++i) {
  171.             printf("\n");
  172.             for (int j = 1; j <= n; ++j) {
  173.                 if (j != 1) printf(" ");
  174.                 printf("%d", rev[arr[i][j]]);
  175.             }
  176.         }
  177.         printf("\n");
  178.  
  179.     }
  180.    
  181.     return 0;
  182. }
Add Comment
Please, Sign In to add comment