#include <cstdio> using namespace std; long long legal_positions(int, int, int); long long legal_positions_aux(int, int); long long legal_positions_parity(int, int, int, int); double of12(int, int, int, int); int canmove(int, int); int n, m; char startboard[8][8]; char endboard[8][8]; const int MAX_N = 64; const int MAX_K = 8; long long binoms[MAX_N+1][MAX_K+1]; int main() { // COMPUTE ALL BINOMS 8x64 for (int i = 0; i <= MAX_N; ++i) { for (int j = 0; j <= MAX_K; ++j) { binoms[i][j] = 0; } } binoms[0][0] = 1; for (int i = 1; i <= MAX_N; ++i) { binoms[i][0] = 1; for (int j = 1; j <= MAX_K; ++j) { binoms[i][j] = binoms[i-1][j-1] + binoms[i-1][j]; } } // END OF BINOMS COMPUTATION int pionkis = 0; scanf("%d %d", &n, &m); for (int i = 0; i < n; ++i) { scanf("%s", startboard[i]); } scanf("\n"); for (int i = 0; i < n; ++i) { scanf("%s", endboard[i]); } int start_parity = 0; int end_parity = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (startboard[i][j] == 'O') { start_parity += i + j; pionkis++; } if (endboard[i][j] == 'O') { end_parity += i + j; } } } start_parity %= 2; end_parity %= 2; if (start_parity != end_parity) { printf("0\n"); return 0; } double of12s = 0; int preposes = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (endboard[i][j] == 'O') { // generate 4 possible pre-moves // i+1, j double a[4]; a[0] = of12(i+1, j, i, j); a[1] = of12(i-1, j, i, j); a[2] = of12(i, j-1, i, j); a[3] = of12(i, j+1, i, j); for (int kk = 0; kk < 4; ++kk) { if (a[kk] != 0) { preposes++; of12s += a[kk]; } } } } } long long all_preposes = legal_positions_parity(n, m, pionkis, 1-end_parity); double x = double(of12s) / (all_preposes); // printf("total possible pre-positions of valid parity: %lld\n", all_preposes); printf("%.15f\n", x); return 0; } int canmove(int i, int j) { // returns 0 if the move is possible, 1 otherwise if (i >= 0 && i < n && j >= 0 && j < m) { // inside the board; if (endboard[i][j] == '.') { return 0; } else { return 1; } } else { return 1; } } double of12(int i, int j, int fi, int fj) { // chance to get to ending position // when fi fj is moved to i j int winning_move = 1; // only i j -> fi fj wins // printf("%d %d: ", i, j); // returns chances of landing in expected position from given pre-position // in terms of n/12 if (i >= 0 && i < n && j >= 0 && j < m) { // inside the board; if (endboard[i][j] == '.') { endboard[i][j] = 'O'; endboard[fi][fj] = '.'; // free spot int total_poss_moves = 0; for (int xi = 0; xi < n; xi++) { for (int xj = 0; xj < m; xj++) { if (endboard[xi][xj] == 'O') { int poss_moves = 4; poss_moves -= canmove(xi + 1, xj); poss_moves -= canmove(xi - 1, xj); poss_moves -= canmove(xi, xj + 1); poss_moves -= canmove(xi, xj - 1); total_poss_moves += poss_moves; } } } // printf("%d possible moves\n", total_poss_moves); endboard[i][j] = '.'; endboard[fi][fj] = 'O'; return 1.0 / total_poss_moves; } else { // printf("\n"); return 0; } } else { // printf("\n"); return 0; } } // = nm choose k long long legal_positions_aux(int nm, int k) { return binoms[nm][k]; } long long legal_positions(int sn, int sm, int k) { int fields = sn*sm; if (fields - k > k) { return legal_positions_aux(fields, k); } else { return legal_positions_aux(fields, fields - k); } } // 0 1 2 3 4 5 // 0 B W B W B W // 1 W B W B W B // 2 B W B W B W long long legal_positions_parity(int sn, int sm, int k, int p) { // p % 2 == 0 -> odd pieces on white fields int starting_k_on_white = p; int total_white = sn*sm/2; int total_black = sn*sm-total_white; long long total_pos = 0; int k_on_white = starting_k_on_white; while(k_on_white <= k) { int k_on_black = k - k_on_white; long long poses = legal_positions_aux(total_black, k_on_black) * legal_positions_aux(total_white, k_on_white); // printf("%d on white (%d), %d on black (%d): %lld\n", k_on_white, total_white, k_on_black, total_black, poses); total_pos += poses; k_on_white += 2; } // legal positions where pawns total x+y %2 = p%2 return total_pos; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #include <cstdio> using namespace std; long long legal_positions(int, int, int); long long legal_positions_aux(int, int); long long legal_positions_parity(int, int, int, int); double of12(int, int, int, int); int canmove(int, int); int n, m; char startboard[8][8]; char endboard[8][8]; const int MAX_N = 64; const int MAX_K = 8; long long binoms[MAX_N+1][MAX_K+1]; int main() { // COMPUTE ALL BINOMS 8x64 for (int i = 0; i <= MAX_N; ++i) { for (int j = 0; j <= MAX_K; ++j) { binoms[i][j] = 0; } } binoms[0][0] = 1; for (int i = 1; i <= MAX_N; ++i) { binoms[i][0] = 1; for (int j = 1; j <= MAX_K; ++j) { binoms[i][j] = binoms[i-1][j-1] + binoms[i-1][j]; } } // END OF BINOMS COMPUTATION int pionkis = 0; scanf("%d %d", &n, &m); for (int i = 0; i < n; ++i) { scanf("%s", startboard[i]); } scanf("\n"); for (int i = 0; i < n; ++i) { scanf("%s", endboard[i]); } int start_parity = 0; int end_parity = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (startboard[i][j] == 'O') { start_parity += i + j; pionkis++; } if (endboard[i][j] == 'O') { end_parity += i + j; } } } start_parity %= 2; end_parity %= 2; if (start_parity != end_parity) { printf("0\n"); return 0; } double of12s = 0; int preposes = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (endboard[i][j] == 'O') { // generate 4 possible pre-moves // i+1, j double a[4]; a[0] = of12(i+1, j, i, j); a[1] = of12(i-1, j, i, j); a[2] = of12(i, j-1, i, j); a[3] = of12(i, j+1, i, j); for (int kk = 0; kk < 4; ++kk) { if (a[kk] != 0) { preposes++; of12s += a[kk]; } } } } } long long all_preposes = legal_positions_parity(n, m, pionkis, 1-end_parity); double x = double(of12s) / (all_preposes); // printf("total possible pre-positions of valid parity: %lld\n", all_preposes); printf("%.15f\n", x); return 0; } int canmove(int i, int j) { // returns 0 if the move is possible, 1 otherwise if (i >= 0 && i < n && j >= 0 && j < m) { // inside the board; if (endboard[i][j] == '.') { return 0; } else { return 1; } } else { return 1; } } double of12(int i, int j, int fi, int fj) { // chance to get to ending position // when fi fj is moved to i j int winning_move = 1; // only i j -> fi fj wins // printf("%d %d: ", i, j); // returns chances of landing in expected position from given pre-position // in terms of n/12 if (i >= 0 && i < n && j >= 0 && j < m) { // inside the board; if (endboard[i][j] == '.') { endboard[i][j] = 'O'; endboard[fi][fj] = '.'; // free spot int total_poss_moves = 0; for (int xi = 0; xi < n; xi++) { for (int xj = 0; xj < m; xj++) { if (endboard[xi][xj] == 'O') { int poss_moves = 4; poss_moves -= canmove(xi + 1, xj); poss_moves -= canmove(xi - 1, xj); poss_moves -= canmove(xi, xj + 1); poss_moves -= canmove(xi, xj - 1); total_poss_moves += poss_moves; } } } // printf("%d possible moves\n", total_poss_moves); endboard[i][j] = '.'; endboard[fi][fj] = 'O'; return 1.0 / total_poss_moves; } else { // printf("\n"); return 0; } } else { // printf("\n"); return 0; } } // = nm choose k long long legal_positions_aux(int nm, int k) { return binoms[nm][k]; } long long legal_positions(int sn, int sm, int k) { int fields = sn*sm; if (fields - k > k) { return legal_positions_aux(fields, k); } else { return legal_positions_aux(fields, fields - k); } } // 0 1 2 3 4 5 // 0 B W B W B W // 1 W B W B W B // 2 B W B W B W long long legal_positions_parity(int sn, int sm, int k, int p) { // p % 2 == 0 -> odd pieces on white fields int starting_k_on_white = p; int total_white = sn*sm/2; int total_black = sn*sm-total_white; long long total_pos = 0; int k_on_white = starting_k_on_white; while(k_on_white <= k) { int k_on_black = k - k_on_white; long long poses = legal_positions_aux(total_black, k_on_black) * legal_positions_aux(total_white, k_on_white); // printf("%d on white (%d), %d on black (%d): %lld\n", k_on_white, total_white, k_on_black, total_black, poses); total_pos += poses; k_on_white += 2; } // legal positions where pawns total x+y %2 = p%2 return total_pos; } |