Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Longest common increasing subsequence of A and B in O(n * m)
- #define MAX 2057
- int lcis(int n, int* A, int m, int* B){
- int i, j, l, res, dp[MAX] = {0};
- for (i = 0; i < n; i++){
- for (l = 0, j = 0; j < m; j++){
- if (A[i] == B[j] && dp[j] <= l) dp[j] = l + 1;
- else if (B[j] < A[i] && dp[j] > l) l = dp[j];
- }
- }
- for (i = 0, res = 0; i < m; i++){
- if (dp[i] > res) res = dp[i];
- }
- return res;
- }
- /// Knight's Tour In Infinite Chessboard
- /// Minimum number of knight moves from (x,y) to (0,0) in non-negative infinite chessboard
- int knight_move(int x, int y){
- int a, b, z, c, d;
- x = abs(x), y = abs(y);
- if (x < y) a = x, x = y, y = a;
- if (x == 2 && y == 2) return 4;
- if (x == 1 && y == 0) return 3;
- if (y == 0 || (y << 1) < x){
- c = y & 1;
- a = x - (c << 1), b = a & 3;
- return ((a - b) >> 1) + b + c;
- }
- else{
- d = x - ((x - y) >> 1);
- z = ((d % 3) != 0), c = (x - y) & 1;
- return ((d / 3) * 2) + c + (z * 2 * (1 - c));
- }
- }
- /// Maximum XOR Subest
- #define MAX 100010
- #define bitlen(x) ((x) == 0 ? (0) : (64 - __builtin_clzll(x)))
- long long ar[MAX];
- long long solve(int n, long long* ar){ /// hash = 220650
- vector <long long> v[64];
- for (int i = 0; i < n; i++) v[bitlen(ar[i])].push_back(ar[i]);
- long long m, x, res = 0;
- for (int i = 63; i > 0; i--){
- int l = v[i].size();
- if (l){
- m = v[i][0];
- res = max(res, res ^ m);
- for (int j = 1; j < l; j++){
- x = m ^ v[i][j];
- if (x) v[bitlen(x)].push_back(x);
- }
- v[i].clear();
- }
- }
- return res;
- }
- /// N queen
- int n, lim, counter;
- void backtrack(int i, int c, int l, int r){
- if (!i){
- counter++;
- return;
- }
- int bitmask, x;
- --i, bitmask = lim & ~(l | r | c);
- while (bitmask){
- x = (-bitmask & bitmask);
- if (!x) return;
- bitmask ^= x;
- backtrack(i, c | x, (l | x) << 1, (r | x) >> 1);
- }
- }
- int main(){
- while (scanf("%d", &n)){
- counter = 0, lim = (1 << n) - 1;
- backtrack(n, 0, 0, 0);
- printf("%d solutions for a %d x %d chessboard\n", counter, n, n);
- }
- return 0;
- }
- /// next small
- #define MAX 250010
- int ar[MAX], L[MAX], R[MAX], stack[MAX], time[MAX];
- void next_small(int n, int* ar, int* L){
- int i, j, k, l, x, top = 0;
- for (i = 0; i < n; i++){
- x = ar[i];
- if (top && stack[top] >= x){
- while (top && stack[top] >= x) k = time[top--];
- L[i] = (i - k + 2);
- stack[++top] = x;
- time[top] = k;
- }
- else{
- L[i] = 1;
- stack[++top] = x;
- time[top] = i + 1;
- }
- }
- }
- /*** L[i] contains maximum length of the range from i to the left such that the minimum of this range
- is not less than ar[i].
- Similarly, R[i] contains maximum length of the range from i to the right such that the minimum
- of this range is not less than ar[i]
- For example, ar[] = 5 3 4 3 1 2 6
- L[] = 1 2 1 4 5 1 1
- R[] = 1 3 1 1 3 2 1
- ***/
- void fill(int n, int* ar, int* L, int* R){
- int i, j, k;
- for (i = 0; i < n; i++) L[i] = ar[n - i - 1];
- next_small(n, L, R);
- next_small(n, ar, L);
- i = 0, j = n - 1;
- while (i < j){
- k = R[i], R[i] = R[j], R[j] = k;
- i++, j--;
- }
- }
- int main(){
- int n, i, j, k;
- scanf("%d", &n);
- for (i = 0; i < n; i++) scanf("%d", &ar[i]);
- fill(n, ar, L, R);
- for (i = 0; i < n; i++) printf("%d ", ar[i]);
- puts("");
- for (i = 0; i < n; i++) printf("%d ", R[i]);
- puts("");
- for (i = 0; i < n; i++) printf("%d ", L[i]);
- puts("");
- return 0;
- }
- /// output compression
- int base = 0, mp[256];
- char digit[256], str[256], temp[256];
- void Generate(){
- int i;
- for (i = 32; i < 127; i++){
- if (i == 32 || i == 34 || i == 39 || i == 44 || i == 92) continue;
- digit[base] = i;
- mp[i] = base;
- base++;
- }
- digit[base] = 0;
- }
- void encode(char* str, int v){
- int i, j, k = 0, l = 0;
- do{
- temp[k++] = digit[v % base];
- v /= base;
- } while (v);
- for (i = k - 1; i >= 0; i--) str[l++] = temp[i];
- str[l] = 0;
- }
- int decode(char* str){
- int i, v = 0;
- for (i = 0; str[i]; i++) v = (v * base) + mp[str[i]];
- return v;
- }
- int main(){
- read();
- Generate();
- encode(str, 12345);
- printf("%d\n", decode(str));
- return 0;
- }
- /// Permutation Index
- #define MAX 12
- #define hash(ar) dp[ar[0]][ar[1]][ar[2]][ar[3]][ar[4]][ar[5]]
- #define lexic(ar) pos[ar[0]][ar[1]][ar[2]][ar[3]][ar[4]][ar[5]]
- char ar[MAX];
- int n, m, counter, factorial[MAX];
- int last[1 << MAX], dp[MAX][MAX][MAX][MAX][MAX][MAX], pos[MAX][MAX][MAX][MAX][MAX][MAX];
- void backtrack(int i, int bitmask, int flag){
- if (i == m){
- if (flag & 1) hash(ar) = ++counter;
- if (flag & 2) lexic(ar) = last[bitmask]++;
- return;
- }
- int j;
- for (j = 0; j < n; j++){
- if (!(bitmask & (1 << j))){
- ar[i] = j;
- backtrack(i + 1, bitmask | (1 << j), flag);
- }
- }
- }
- void Generate(){
- int i, j;
- clr(ar), clr(last);
- counter = 0, m = n >> 1, factorial[0] = 1;
- for (i = 1; i < MAX; i++) factorial[i] = factorial[i - 1] * i;
- if (n & 1){
- backtrack(0, 0, 1);
- m++;
- backtrack(0, 0, 2);
- m--;
- }
- else backtrack(0, 0, 3);
- }
- int F(int P[MAX]){
- int i, a = 0, b = 0;
- char A[6] = {0}, B[6] = {0};
- for (i = 0; i < m; i++) A[a++] = P[i];
- for (i = m; i < n; i++) B[b++] = P[i];
- return ((hash(A) - 1) * factorial[b]) + lexic(B) + 1;
- }
- int main(){
- int i, j, P[MAX];
- while (scanf("%d", &n) != EOF){
- Generate();
- for (i = 0; i < n; i++) scanf("%d", &P[i]);
- for (i = 0; i < n; i++) P[i]--;
- int res = F(P);
- printf("%d\n", res);
- }
- return 0;
- }
- /// Permutation Rank
- /// Find's the rank of permutation
- /// Rank and permutation elements are 1 base indexed
- long long find_rank(vector <int> permutation){
- long long res = 1;
- int i, j, n = permutation.size();
- vector <bool> visited(n + 1, false);
- vector <long long> factorial(n + 1, 1);
- for (i = 1; i <= n; i++) factorial[i] = factorial[i - 1] * i;
- for (i = 1; i <= n; i++){
- for (j = 1; j <= n; j++){
- if (!visited[j]){
- if (permutation[i - 1] == j){
- visited[j] = true;
- break;
- }
- res += factorial[n - i];
- }
- }
- }
- return res;
- }
- /// Find's the k'th permutation of 1 to n
- /// Rank and permutation elements are 1 base indexed
- vector <int> find_rank(int n, long long k){
- int i, j;
- vector <int> res(n, 0);
- vector <bool> visited(n + 1, false);
- vector <long long> factorial(n + 1, 1);
- for (i = 1; i <= n; i++) factorial[i] = factorial[i - 1] * i;
- for (i = 1; i <= n; i++){
- for (j = 1; j <= n; j++){
- if (!visited[j]){
- if (factorial[n - i] >= k){
- visited[j] = true;
- res[i - 1] = j;
- break;
- }
- k -= factorial[n - i];
- }
- }
- }
- return res;
- }
- /// Josephus
- /// Josephus problem, n people numbered from 1 to n stand in a circle.
- /// Counting starts from 1 and every k'th people dies
- /// Returns the position of the m'th killed people
- /// For example if n = 10 and k = 3, then the people killed are 3, 6, 9, 2, 7, 1, 8, 5, 10, 4 respectively
- /// O(n)
- int josephus(int n, int k, int m){
- int i;
- for (m = n - m, i = m + 1; i <= n; i++){
- m += k;
- if (m >= i) m %= i;
- }
- return m + 1;
- }
- /// O(k log(n))
- long long josephus2(long long n, long long k, long long m){ /// hash = 583016
- m = n - m;
- if (k <= 1) return n - m;
- long long i = m;
- while (i < n){
- long long r = (i - m + k - 2) / (k - 1);
- if ((i + r) > n) r = n - i;
- else if (!r) r = 1;
- i += r;
- m = (m + (r * k)) % i;
- }
- return m + 1;
- }
- int main(){
- int n, k, m;
- printf("%d\n", josephus(10, 1, 2));
- printf("%d\n", josephus(10, 1, 10));
- }
- /// IDAStar
- int ida(int g, int lim, int l, int last, int idx){ /// last = last taken move, don't go there!
- int h = heuristic(l);
- if (!h){ /// Goal reached
- sequence[idx] = 0;
- puts(sequence);
- return g;
- }
- int f = g + h;
- if (f > lim) return f;
- int i, j, res = inf;
- for (i = 0; i < 12; i++){
- if (dis[l][i] == 1 && i != last){
- sequence[idx] = str[i];
- swap(str[l], str[i]);
- int x = ida(g + 1, lim, i, l, idx + 1);
- if (x < res) res = x; /// Update next limit in iterative deepening
- swap(str[l], str[i]);
- if (res <= lim) return res; /// Since iterative deepening, return if solution found
- }
- }
- return res;
- }
- int Solve(int l){
- int lim = heuristic(l);
- for (; ;){
- int nlim = ida(0, lim, l, l, 0);
- if (nlim <= lim) return nlim;
- else lim = nlim;
- }
- return -1;
- }
- /// Histogram Area
- #define MAX 2010
- int n, ar[MAX];
- /*** Largest area in a histogram ***/
- /*** Be careful, long long might be required ***/
- int histogram(int n, int* ar){
- int i = 0, j, a, x, top = 0, res = 0;
- stack[0] = -1;
- while (i < n){
- if (!top || (ar[stack[top]] <= ar[i]) ) stack[++top] = i++;
- else{
- x = stack[top--];
- a = ar[x] * (i - stack[top] - 1);
- if (a > res) res = a;
- }
- }
- while (top){
- x = stack[top--];
- a = ar[x] * (i - stack[top] - 1);
- if (a > res) res = a;
- }
- return res;
- }
- /// HashMap
- using namespace std;
- struct hashmap{
- int t, sz, hmod;
- vector <int> id;
- vector <long long> key, val;
- inline int nextPrime(int n){
- for (int i = n; ;i++){
- for (int j = 2; ;j++){
- if ((j * j) > i) return i;
- if ((i % j) == 0) break;
- }
- }
- return -1;
- }
- void clear(){t++;}
- inline int pos(unsigned long long x){
- int i = x % hmod;
- while (id[i] == t && key[i] != x) i++;
- return i;
- }
- inline void insert(long long x, long long v){
- int i = pos(x);
- if (id[i] != t) sz++;
- key[i] = x, val[i] = v, id[i] = t;
- }
- inline void erase(long long x){
- int i = pos(x);
- if (id[i] == t) key[i] = 0, val[i] = 0, id[i] = 0, sz--;
- }
- inline long long find(long long x){
- int i = pos(x);
- return (id[i] != t) ? -1 : val[i];
- }
- inline bool contains(long long x){
- int i = pos(x);
- return (id[i] == t);
- }
- inline void add(long long x, long long v){
- int i = pos(x);
- (id[i] == t) ? (val[i] += v) : (key[i] = x, val[i] = v, id[i] = t, sz++);
- }
- inline int size(){
- return sz;
- }
- hashmap(){}
- hashmap(int m){
- srand(time(0));
- m = (m << 1) - ran(1, m);
- hmod = nextPrime(max(100, m));
- sz = 0, t = 1;
- id.resize(hmod + 0x1FF, 0);
- key.resize(hmod + 0x1FF, 0), val.resize(hmod + 0x1FF, 0);
- }
- };
- /// HakmemItem175
- /// Only for non-negative integers
- /// Returns the immediate next number with same count of one bits, -1 on failure
- long long hakmemItem175(long long n){
- if (n == 0) return -1;
- long long x = (n & -n);
- long long left = (x + n);
- long long right = ((n ^ left) / x) >> 2;
- long long res = (left | right);
- return res;
- }
- /// Returns the immediate previous number with same count of one bits, -1 on failure
- long long lol(long long n){
- if (n == 0 || n == 1) return -1;
- long long res = ~hakmemItem175(~n);
- return (res == 0) ? -1 : res;
- }
- /// Greedy Coin Change
- const int n = 10;
- const long long INF = 0x7FFFFFFFFFFFFFFF;
- const int coins[] = {0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000}; /// 1 based indexing for coins
- long long res, counter[44], sum[44]; /// counter[i] = number of coins of type i
- void backtrack(int i, long long p, long long c){ /// Complexity 2^n
- if (p == 0 && c < res) res = c; /// Change min to max here
- if (i == 0 || p <= 0) return;
- long long k, x = 0;
- if ((p - sum[i - 1]) > x) x = p - sum[i - 1];
- k = (x / coins[i]) + (x % coins[i] != 0);
- if (k <= counter[i]) backtrack(i - 1, p - k * coins[i], c + k);
- if (++k <= counter[i]) backtrack(i - 1, p - k * coins[i], c + k); /// Do this multiple times if WA (around 5 or 10 should do)
- }
- /// Minimum number of coins required to make s from coin values and count of coin values
- /// -1 if no solution
- long long solve(long long s){
- int i, j;
- for (i = 1; i <= n; i++) sum[i] = sum[i - 1] + coins[i] * counter[i];
- res = INF;
- backtrack(n, s, 0);
- if (res == INF) res = -1;
- return res;
- }
- /// gray codes
- long long gray_code(long long x){
- return x ^ (x >> 1);
- }
- long long inverse_gray_code(long long x){
- long long h = 1, res = 0;
- do{
- if (x & 1) res ^= h;
- x >>= 1, h = (h << 1) + 1;
- } while (x);
- return res;
- }
- /// Gambler's ruin problem
- /// First player has n1 coins, second player has n2 coins
- /// After each move, first player wins with probability p and second player wins with probability q (p + q == 1)
- /// The loser gives 1 coin to the winner
- /// When number of coins reaches 0, a player loses
- /// Returns the probability of first player winning
- long double expo(long double x, int n){
- if (n == 0) return 1;
- if (n & 1) return expo(x, n - 1) * x;
- else{
- long double res = expo(x, n >> 1);
- return res * res;
- }
- }
- long double gamblers_ruin(int n1, int n2, long double p, long double q){
- if (fabs(p - q) <= 1e-9){
- return (long double)n2 / (n1 + n2);
- }
- long double x = 1.0 - expo(q / p, n2);
- long double y = 1.0 - expo(q / p, n1 + n2);
- return (x / y);
- }
- /// Faulhaber's Formula
- #define MAX 2510
- #define MOD 1000000007
- int S[MAX][MAX], inv[MAX];
- int expo(long long x, int n){
- x %= MOD;
- long long res = 1;
- while (n){
- if (n & 1) res = (res * x) % MOD;
- x = (x * x) % MOD;
- n >>= 1;
- }
- return (res % MOD);
- }
- void Generate(){
- int i, j;
- for (i = 0; i < MAX; i++) inv[i] = expo(i, MOD - 2);
- S[0][0] = 1;
- for (i = 1; i < MAX; i++){
- S[i][0] = 0;
- for (j = 1; j <= i; j++){
- S[i][j] = ( ((long long)S[i - 1][j] * j) + S[i - 1][j - 1]) % MOD;
- }
- }
- }
- int faulhaber(long long n, int k){
- n %= MOD;
- if (!k) return n;
- int j;
- long long res = 0, p = 1;
- for (j = 0; j <= k; j++){
- p = (p * (n + 1 - j)) % MOD;
- res = (res + (((S[k][j] * p) % MOD) * inv[j + 1])) % MOD;
- }
- return (res % MOD);
- }
- int main(){
- Generate();
- printf("%d\n", faulhaber(1001212, 1000));
- return 0;
- }
- /// Faulhaber's Formula (Custom Algorithm)
- #define MAX 1010
- #define MOD 1000000007
- namespace fool{
- #define MAXN 10000
- tr1::unordered_map <unsigned long long, int> mp;
- int inv, P[MAX], binomial[MAX][MAX], dp[MAXN][MAX];
- long long expo(long long x, long long n){
- x %= MOD;
- long long res = 1;
- while (n){
- if (n & 1) res = (res * x) % MOD;
- x = (x * x) % MOD;
- n >>= 1;
- }
- return (res % MOD);
- }
- void init(){
- int i, j;
- mp.clear();
- inv = expo(2, MOD - 2);
- P[0] = 1;
- for (i = 1; i < MAX; i++){
- P[i] = (P[i - 1] << 1);
- if (P[i] >= MOD) P[i] -= MOD;
- }
- for (i = 0; i < MAX; i++){
- for (j = 0; j <= i; j++){
- if (i == j || !j) binomial[i][j] = 1;
- else{
- binomial[i][j] = (binomial[i - 1][j] + binomial[i - 1][j - 1]);
- if (binomial[i][j] >= MOD) binomial[i][j] -= MOD;
- }
- }
- }
- for (i = 1; i < MAXN; i++){
- long long x = 1;
- for (j = 0; j < MAX; j++){
- dp[i][j] = dp[i - 1][j] + x;
- if (dp[i][j] >= MOD) dp[i][j] -= MOD;
- x = (x * i) % MOD;
- }
- }
- }
- /// Returns (1^k + 2^k + 3^k + .... n^k) % MOD
- long long F(unsigned long long n, int k){
- if (n < MAXN) return dp[n][k];
- if (n == 1) return 1;
- if (n == 2) return (P[k] + 1) % MOD;
- if (!k) return (n % MOD);
- if (k == 1){
- n %= MOD;
- return (((n * (n + 1)) % MOD) * inv) % MOD;
- }
- unsigned long long h = (n << 10LL) | k; /// Change hash function according to limits of n and k
- long long res = mp[h];
- if (res) return res;
- if (n & 1) res = F(n - 1, k) + expo(n, k);
- else{
- long long m, z;
- m = n >> 1;
- res = (F(m, k) * P[k]) % MOD;
- m--, res++;
- for (int i = 0; i <= k; i++){
- z = (F(m, i) * binomial[k][i]) % MOD;
- z = (z * P[i]) % MOD;
- res += z;
- }
- }
- res %= MOD;
- return (mp[h] = res);
- }
- long long faulhaber(unsigned long long n, int k){
- ///fool::init();
- return F(n, k);
- }
- }
- int main(){
- fool::init();
- int t, i, j;
- long long n, k, res;
- cin >> t;
- while (t--){
- cin >> n >> k;
- res = fool::faulhaber(n, k);
- cout << res << endl;
- }
- return 0;
- }
- /// CKY algo
- The Cocke–Younger–Kasami algorithm (alternatively called CYK, or CKY) is a parsing algorithm for context-free grammars,
- named after its inventors, John Cocke, Daniel Younger and Tadao Kasami. It employs bottom-up parsing and dynamic programming.
- The standard version of CYK operates only on context-free grammars given in Chomsky normal form (CNF).
- However any context-free grammar may be transformed to a CNF grammar expressing the same language.
- The importance of the CYK algorithm stems from its high efficiency in certain situations. Using Landau symbols,
- the worst case running time of CYK is O(N^3 * |G|), where N is the length of the parsed string and |G| is the
- size of the CNF grammar G. This makes it one of the most efficient parsing algorithms in terms of worst-case
- asymptotic complexity, although other algorithms exist with better average running time in many practical scenarios.
- Pseudocode:
- let the input be a string S consisting of n characters: a1 ... an.
- let the grammar contain r nonterminal symbols R1 ... Rr.
- This grammar contains the subset Rs which is the set of start symbols.
- let P[n,n,r] be an array of booleans. Initialize all elements of P to false.
- for each i = 1 to n
- for each unit production Rj -> ai
- set P[1,i,j] = true
- for each i = 2 to n -- Length of span
- for each j = 1 to n-i+1 -- Start of span
- for each k = 1 to i-1 -- Partition of span
- for each production RA -> RB RC
- if P[k,j,B] and P[i-k,j+k,C] then set P[i,j,A] = true
- if any of P[n,1,x] is true (x is iterated over the set s, where s are all the indices for Rs) then
- S is member of language
- else
- S is not member of language
- /// Combsort
- #define MAX 1000010
- int n, ar[MAX];
- void combsort(int n, int* ar){
- if (n <= 1) return;
- int i, j, x, g = n, flag = 0;
- while ((g != 1) || flag){
- flag = 0;
- if (g != 1) g *= 0.77425;
- for (i = 0; (i + g) < n; i++){
- if (ar[i] > ar[i + g]){
- flag = 1;
- x = ar[i], ar[i] = ar[i + g], ar[i + g] = x;
- }
- }
- }
- }
- int main(){
- int i, j;
- n = MAX - 10;
- for (i = 0; i < n; i++) ar[i] = (rand() << 15 ^ rand()) % MAX;
- combsort(n, ar);
- for (i = 0; (i + 1) < n; i++){
- if (ar[i] > ar[i + 1]) puts("fail");
- }
- return 0;
- }
- /// bit hacks
- unsigned int reverse_bits(unsigned int v){
- v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
- v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
- v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
- v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
- return ((v >> 16) | (v << 16));
- }
- /// Returns i if x = 2^i and 0 otherwise
- int bitscan(unsigned int x){
- __asm__ volatile("bsf %0, %0" : "=r" (x) : "0" (x));
- return x;
- }
- /// Returns next number with same number of 1 bits
- unsigned int next_combination(unsigned int x){
- unsigned int y = x & -x;
- x += y;
- unsigned int z = x & -x;
- z -= y;
- z = z >> bitscan(z & -z);
- return x | (z >> 1);
- }
- /// Bitset Iteration
- char bithash[67];
- void init(){
- int i;
- for (i = 0; i < 64; i++) bithash[(1ULL << i) % 67] = i;
- }
- void iterate(unsigned long long x){
- while (x){
- unsigned long long y = (x & -x);
- int i = bithash[y % 67];
- x ^= y;
- printf("%d\n", i);
- }
- }
- int main(){
- init();
- unsigned long long x = 0b100000001011000100100101001010101001010100;
- iterate(x);
- return 0;
- }
- /// Algorithm X + Dancing Links
- #define MAXR 100010
- #define MAXC 100010
- #define MAXNODE 100010
- /// Define MAX limits appropriately, set to large values for safety
- /// Dancing Links data structure to solve exact cover problems
- /// There are some constraints as columns and a number of rows
- /// Each row satisfies some constraints
- /// Objective is to select a subset of rows so that each constraint is satisfied exactly once
- /// Don't forget to initialize first by calling init()
- namespace dlx{ /// hash = 641985
- int row[MAXNODE], col[MAXNODE];
- int L[MAXNODE], R[MAXNODE], U[MAXNODE], D[MAXNODE];
- int n, idx, len, selected_rows[MAXR], column_count[MAXC];
- void init(int ncolumn){ /// initialize first with total number of columns (1 based)
- memset(column_count, 0, sizeof(column_count));
- n = ncolumn, idx = n + 1;
- for (int i = 0; i <= n; i++) U[i] = D[i] = i, L[i] = i - 1, R[i] = i + 1;
- L[0] = n, R[n] = 0;
- }
- /// r = index of row (1 based)
- /// the vector columns contain the columns which are satisfied with this row
- inline void addrow(int r, vector <int>& columns){ /// hash = 438353
- int i, c, l = columns.size(), first = idx;
- for (i = 0; i < l; i++){
- c = columns[i];
- L[idx] = idx - 1, R[idx] = idx + 1, D[idx] = c, U[idx] = U[c];
- D[U[c]] = idx, U[c] = idx, row[idx] = r, col[idx] = c;
- column_count[c]++, idx++; /// column_count[c] is the number of rows which satisfies constraint column c
- }
- R[idx - 1] = first, L[first] = idx - 1;
- }
- /// Removes column c from the structure
- inline void remove(int c){ /// hash = 377852
- L[R[c]] = L[c], R[L[c]] = R[c];
- for (int i = D[c]; i != c; i = D[i]){
- for (int j = R[i]; j != i; j = R[j]){
- column_count[col[j]]--;
- U[D[j]] = U[j], D[U[j]] = D[j];
- }
- }
- }
- /// Restores the position of column c in the structure
- inline void restore(int c){ /// hash = 804101
- for (int i = U[c]; i != c; i = U[i]){
- for (int j = L[i]; j != i; j = L[j]){
- column_count[col[j]]++;
- U[D[j]] = j, D[U[j]] = j;
- }
- }
- L[R[c]] = c, R[L[c]] = c;
- }
- /// Recursively enumerate to solve exact cover
- bool algorithmX(int depth){ /// hash = 308201
- if(R[0] == 0){
- len = depth;
- return true;
- }
- int i, j, c = R[0];
- for (i = R[0]; i != 0; i = R[i]){ /// Select a column deterministically
- if(column_count[i] < column_count[c]) c = i; /// if multiple columns exist, choose the one with minimum count
- }
- remove(c);
- bool flag = false;
- for (i = D[c]; i != c && !flag; i = D[i]){ /// While solution is not found
- selected_rows[depth] = row[i];
- for (j = R[i]; j != i; j = R[j]) remove(col[j]);
- flag |= algorithmX(depth + 1); /// May be select rows non-deterministically here with random_shuffle?
- for (j = L[i]; j != i; j = L[j]) restore(col[j]);
- }
- restore(c);
- return flag;
- }
- bool exact_cover(vector<int>& rows){ /// Returns the subset of rows satisfying exact cover, false otherwise
- rows.clear();
- if(!algorithmX(0)) return false;
- for(int i = 0; i < len; i++) rows.push_back(selected_rows[i]);
- return true;
- }
- }
- namespace sudoku{
- inline int encode(int n, int a, int b, int c){ /// Encode information
- return (a * n * n) + (b * n) + c + 1;
- }
- inline void decode(int n, int v, int& a, int& b, int& c){ /// Decode information
- v--;
- c = v % n, v /= n;
- b = v % n, a = (v / n) % n;
- }
- bool solve(int n, int ar[25][25]){
- int i, j, k, l, c;
- int m = sqrt(n + 0.5); /// m * m sub-grid
- int ncolumn = n * n * 4; /// n * n for cells, n * n for rows, n * n for columns and n * n for boxes
- dlx::init(ncolumn);
- for (i = 0; i < n; i++){
- for (j = 0; j < n; j++){
- for (k = 0; k < n; k++){
- if (ar[i][j] == 0 || ar[i][j] == (k + 1)){
- vector <int> columns;
- columns.push_back(encode(n, 0, i, j)); /// Each cell can contain only 1 value
- columns.push_back(encode(n, 1, i, k)); /// Row[i] can contain only ar[i][j], if ar[i][j] != 0, otherwise it can contain any value
- columns.push_back(encode(n, 2, j, k)); /// Column[j] can contain only ar[i][j], if ar[i][j] != 0, otherwise it can contain any value
- columns.push_back(encode(n, 3, (i / m) * m + j / m, k)); /// Similarly for box numbered i / m * m + j / m
- /// Current row selection, place number k in the cell[i][j] and doing so will cover all columns in the columns vector
- int cur_row = encode(n, i, j, k);
- dlx::addrow(cur_row, columns);
- }
- }
- }
- }
- vector<int> res;
- if (!dlx::exact_cover(res)) return false;
- for (l = 0; l < res.size(); l++){
- decode(n, res[l], i, j, k);
- ar[i][j] = k + 1;
- }
- return true;
- }
- }
- /// 15-Puzzle (Manhattan distance + Linear conflict heuristic)
- #define inf 1010
- #define swap(x, y) (x ^= y, y ^= x, x ^= y)
- #define F(i, j) (abs(((ar[i][j] - 1) >> 2) - i) + abs( ((ar[i][j] - 1) & 3) - j))
- bool flag;
- char str[60];
- char dir[] = "LRUD";
- int dx[] = {0, 0, -1, 1};
- int dy[] = {-1, 1, 0, 0};
- int len[4] = {0}, idx[4][4], ar[4][4], transpose[4][4];
- int row_conflict(int rc){
- int i, j, k, x, y, res = 0;
- for (i = 0; i < 4; i++){
- x = (ar[rc][i] >> 2);
- if (ar[rc][i] != 16) idx[x][len[x]++] = ar[rc][i];
- }
- for (i = 0; i < 4; i++){
- if (len[i] > 1){
- for (j = 0; j < len[i]; j++){
- for (k = j + 1; k < len[i]; k++){
- if (idx[i][j] > idx[i][k]) res += 2;
- }
- }
- }
- len[i] = 0;
- }
- return res;
- }
- int column_conflict(int rc){
- int i, j, k, x, y, res = 0;
- for (i = 0; i < 4; i++){
- x = (ar[i][rc] & 3);
- if (ar[i][rc] != 16) idx[x][len[x]++] = ar[i][rc];
- }
- for (i = 0; i < 4; i++){
- if (len[i] > 1){
- for (j = 0; j < len[i]; j++){
- for (k = j + 1; k < len[i]; k++){
- if (idx[i][j] > idx[i][k]) res += 2;
- }
- }
- }
- len[i] = 0;
- }
- return res;
- }
- int heuristic(int bx, int by){
- int i, j, k, l, res, linear_conflict = 0, manhattan_distance = 0;
- for (i = 0; i < 4; i++){
- for (j = 0; j < 4; j++){
- transpose[j][i] = ar[i][j];
- if (ar[i][j] != 16){
- manhattan_distance += F(i, j);
- }
- }
- linear_conflict += row_conflict(i);
- linear_conflict += column_conflict(i);
- }
- res = manhattan_distance + linear_conflict;
- return res;
- }
- int ida(int bx, int by, int lx, int ly, int g, int lim, int d, int h){
- if (flag) return;
- if (!h){
- if (!flag){
- flag = true;
- str[d] = 0;
- puts(str);
- }
- return g;
- }
- int f = g + h;
- if (f > lim) return f;
- int i, k, l, nh, r, res = inf;
- for (i = 0; i < 4; i++){
- k = bx + dx[i], l = by + dy[i];
- if (k >= 0 && k < 4 && l >= 0 && l < 4 && !(k == lx && l == ly)){
- nh = h;
- nh -= F(k, l);
- if (bx != k) nh -= row_conflict(bx), nh -= row_conflict(k);
- if (by != l) nh -= column_conflict(by), nh -= column_conflict(l);
- swap(ar[bx][by], ar[k][l]);
- nh += F(bx, by);
- if (bx != k) nh += row_conflict(bx), nh += row_conflict(k);
- if (by != l) nh += column_conflict(by), nh += column_conflict(l);
- str[d] = dir[i];
- r = ida(k, l, bx, by, g + 1, lim, d + 1, nh);
- swap(ar[bx][by], ar[k][l]);
- if (r < res) res = r;
- if (r <= lim) return r;
- }
- }
- return res;
- }
- int Solve(int bx, int by){
- int res, lim = heuristic(bx, by);
- flag = false;
- for (; ;){
- res = ida(bx, by, bx, by, 0, lim, 0, heuristic(bx, by));
- if (res <= lim) return res;
- else lim = res;
- }
- }
- bool Solvable(int bx, int by){
- int i, j, r = 0, counter = 0;
- for (i = 0; i < 16; i++){
- if (ar[i >> 2][i & 3] == 16) r = (i >> 2);
- else{
- for (j = i + 1; j < 16; j++){
- if (ar[j >> 2][j & 3] < ar[i >> 2][i & 3]) counter++;
- }
- }
- }
- return ((counter + r) & 1);
- }
- int main(){
- int t, i, j, k, bx, by;
- scanf("%d", &t);
- while (t--){
- for (i = 0; i < 4; i++){
- for (j = 0; j < 4; j++){
- scanf("%d", &ar[i][j]);
- if (!ar[i][j]){
- bx = i, by = j;
- ar[i][j] = 16;
- }
- }
- }
- if (!Solvable(bx, by)) puts("This puzzle is not solvable.");
- else{
- int res = Solve(bx, by);
- if (res > 50) puts("This puzzle is not solvable.");
- }
- }
- return 0;
- }
- /*
- 5
- 2 3 4 0
- 1 5 7 8
- 9 6 10 12
- 13 14 11 15
- 6 2 8 4
- 12 14 1 10
- 13 15 3 9
- 11 0 5 7
- 6 8 4 2
- 12 14 1 10
- 13 15 3 9
- 11 0 5 7
- 13 1 2 4
- 5 0 3 7
- 9 6 10 12
- 15 8 11 14
- 0 12 9 13
- 15 11 10 14
- 3 7 2 5
- 4 8 6 1
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement