├── Problem explanation.txt ├── Time Complexity.txt ├── Code(Python).py ├── Algorithm.txt ├── Code(C++).cpp └── Code(java).java /Problem explanation.txt: -------------------------------------------------------------------------------- 1 | The problem is asking you to construct a Bash matrix based on a given set of notes. A Bash matrix is an N by N matrix where each cell contains one of the characters 'U', 'D', 'L', or 'R'. The goal is to find the smallest possible cost for the matrix that satisfies the given notes. 2 | 3 | The notes indicate the path Chef took in the matrix. He starts in a cell and follows the instructions in each cell until he either reaches a previously visited cell or leaves the matrix. The stopping cell is the first cell he visits twice during this process. 4 | 5 | The input consists of the matrix size N, followed by the costs for each character ('U', 'L', 'D', 'R'), and the coordinates for each cell in the matrix. The coordinates indicate the row and column of the cells that Chef visited in his path. 6 | 7 | The output should be the minimum cost of the Bash matrix and the matrix itself, represented as N+1 lines. Each line represents a row in the matrix. 8 | 9 | If it is not possible to construct a Bash matrix that satisfies the given notes, the output should be -1. -------------------------------------------------------------------------------- /Time Complexity.txt: -------------------------------------------------------------------------------- 1 | Here's a general breakdown of the time complexity for different parts of the code: 2 | 3 | 1. Reading Input: O(N^2) 4 | - The input consists of N lines, each containing 2N space-separated integers. 5 | - Reading these integers would take O(N^2) time. 6 | 7 | 2. Constructing the Bash Matrix: O(N^2) 8 | - The Bash matrix is an N by N matrix, so constructing it would take O(N^2) time. 9 | 10 | 3. Checking Validity of the Bash Matrix: O(N^2) 11 | - To check the validity of the Bash matrix, we need to simulate Chef's movement based on the instructions in each cell. 12 | - This would require traversing each cell of the matrix, resulting in a time complexity of O(N^2). 13 | 14 | 4. Finding the Minimum Cost: O(N) 15 | - To find the minimum cost, we need to iterate over each character in the Bash matrix and sum up the corresponding costs. 16 | - Since the Bash matrix has N rows and N columns, the total number of characters is N^2. 17 | - Thus, finding the minimum cost would take O(N^2) time. 18 | 19 | Overall, the dominant factor in the time complexity would be O(N^2) due to the simulation of Chef's movement and the finding of the minimum cost. The other parts, such as input reading and matrix construction, have a time complexity of O(N^2) as well but have a lesser impact on the overall complexity. -------------------------------------------------------------------------------- /Code(Python).py: -------------------------------------------------------------------------------- 1 | 2 | import os, sys, bisect 3 | from collections import defaultdict, Counter, deque; 4 | from functools import lru_cache #use @lru_cache(None) 5 | if os.path.exists('in.txt'): sys.stdin=open('in.txt','r') 6 | if os.path.exists('out.txt'): sys.stdout=open('out.txt', 'w') 7 | # 8 | input = lambda: sys.stdin.readline().strip() 9 | imap = lambda: map(int,input().split()); ilist = lambda: list(imap()) 10 | #------------------------------------------------------------------ 11 | sys.setrecursionlimit(10**6) 12 | mod = int(1e9+7) 13 | 14 | n = int(input()) 15 | p = ilist() 16 | inp = [['']*n for i in range(n)] 17 | 18 | q = deque() 19 | st = set() 20 | src = set() 21 | for i in range(n): 22 | a = [x-1 for x in imap()] 23 | for j in range(n): 24 | inp[i][j] = (a[2*j], a[2*j+1]) 25 | if inp[i][j]!=(i,j): 26 | x,y = inp[i][j] 27 | src.add((x,y,(x,y))) 28 | st.add((x,y)) 29 | sym = "ULDR" 30 | rSym = "DRUL" 31 | dirs = [[-1,0],[0,-1],[1,0],[0,1]] 32 | q = deque(src) 33 | res = [['']*n for i in range(n)] 34 | while q: 35 | i,j,pr = q.popleft() 36 | for idx,[dx,dy] in enumerate(dirs): 37 | x,y = i+dx,j+dy 38 | if 0<=xN and j>N: break 132 | x,y =decomp[i],decomp[j] 133 | dif = [y[0]-x[0],y[1]-x[1]] 134 | if dif in dirs: 135 | idx = dirs.index(dif) 136 | res[x[0]][x[1]] = sym[idx] 137 | res[y[0]][y[1]] = rSym[idx] 138 | else: 139 | print(-1) 140 | exit() 141 | cnt = 0 142 | cost = 0 143 | for i in range(n): 144 | for j in range(n): 145 | if res[i][j] in "ULDR": 146 | cost+=p[sym.index(res[i][j])] 147 | cnt+=1 148 | def check(inp, res, n): 149 | def dfs(i,j, vis): 150 | dx,dy = dirs[sym.index(res[i][j])] 151 | x,y = i+dx,j+dy 152 | if 0<=x 2 | using namespace std; 3 | #define F first 4 | #define S second 5 | #define ignore ignore 6 | #define pb emplace_back 7 | #define mt make_tuple 8 | #define gcd __gcd 9 | // Input 10 | #define in(a) scanf("%d",&a) 11 | #define in2(a,b) scanf("%d%d",&a,&b) 12 | #define in3(a,b,c) scanf("%d%d%d",&a,&b,&c) 13 | #define in4(a,b,c,d) scanf("%d%d%d%d",&a,&b,&c,&d) 14 | #define inp(p) in2(p.F,p.S) 15 | #define llin(a) cin >> a 16 | #define llin2(a,b) cin >> a >> b 17 | #define llin3(a,b,c) cin >> a >> b >> c 18 | #define inl(a) scanf("%lld",&a) 19 | #define read(v,i,n) for(i=0;i=0;--i) 45 | #define lp(i,a,b) for(i=a;i=b;--i) 47 | #define all(vec) vec.begin(),vec.end() 48 | #define lower(v,k) lower_bound(v.begin(),v.end(),k)-v.begin() 49 | #define upper(v,k) upper_bound(v.begin(),v.end(),k)-v.begin() 50 | #define tf(mytuple) get<0>(mytuple) 51 | #define ts(mytuple) get<1>(mytuple) 52 | #define tt(mytuple) get<2>(mytuple) 53 | // function 54 | #define sz(x) (int)x.size() 55 | #define inrange(i,a,b) (i>=a && i<=b) 56 | #define FLUSH fflush(stdout) 57 | #define precision(x) cout << setprecision(x) << fixed 58 | #define remax(a,b) a=max(a,b) 59 | #define remin(a,b) a=min(a,b) 60 | #define middle() ((l+h)/2) 61 | #define lchild(p) 2*p 62 | #define rchild(p) 2*p+1 63 | #define lseg l,m,2*p 64 | #define rseg m+1,h,2*p+1 65 | #define bhardo(mat,i,j,n,m,t) rep(i,n){rep(j,m)mat[i][j]=t;} 66 | #define baselog2(n) __lg(n) 67 | #define numberofbit(n) (32-__builtin_clz(n)) 68 | #define numberofbitll(n) (64-__builtin_clzll(n)) 69 | #define onbitcount(x) __builtin_popcount(x) 70 | #define onbitcountll(x) __builtin_popcountll(x) 71 | #define biton(mask,i) ((mask>>i)&1) 72 | #define bitoff(mask,i) (!((mask>>i)&1)) 73 | #define toggle(mask,i) (mask^=(1<<(i))) 74 | #define raise(i) (1<<(i)) 75 | #define mul(p,q) ((ll)(p)*(ll)(q)) 76 | // Debug 77 | #define dbg(v,i,n) for(i=0;i _it(_ss); err(_it, args); } 80 | void err(istream_iterator it) {} 81 | template 82 | void err(istream_iterator it, T a, Args... args) 83 | { 84 | cerr << *it << " = " << a << "\n"; 85 | err(++it, args...); 86 | } 87 | // Data Type 88 | #define ll long long int 89 | #define ii pair 90 | #define pli pair 91 | #define lii pair 92 | #define triple tuple 93 | #define vi vector 94 | #define vll vector 95 | #define vii vector > 96 | #define vvi vector > 97 | #define viii vector,int> > 98 | #define vvii vector > > 99 | // Constant 100 | const double PI = acos(-1); 101 | const double eps = (1e-9); 102 | const ll INF = 2e18; 103 | const int M = (1e9)+7; 104 | //const int M= 998244353; 105 | const int N = 53; // check the limit, man 106 | /** 107 | Have you worked on Simplification of Idea? 108 | Ok! let's code, check whether it is correct or not? 109 | */ 110 | struct bipartite_matching // Hopcroft-Karp Algorithm works in O(E*sqrt(V)) 111 | { 112 | int n,m,root=0; 113 | // n nodes on left side numbered [1,n] and m nodes on right side numbered [n+1,n+m] 114 | vector > graph; 115 | vector lev,match; 116 | bipartite_matching(int l,int r) : n(l),m(r),graph(l+1),lev(l+1),match(l+r+1) {} 117 | void add_edge(int a,int b) // 1-indexing, a->[1,n] and b->[1,m] 118 | { 119 | graph[a].pb(n+b); 120 | } 121 | bool bfs() 122 | { 123 | queue pq; 124 | fill(all(lev),M); 125 | for(int i=1;i<=n;i++)if(match[i]==root)lev[i]=0,pq.push(i); 126 | while(!pq.empty()) 127 | { 128 | int s=pq.front(); pq.pop(); 129 | for(auto a : graph[s]) 130 | if(lev[match[a]]==M)lev[match[a]]=lev[s]+1,pq.push(match[a]); 131 | } 132 | return (lev[root]!=M); 133 | } 134 | bool dfs(int s) 135 | { 136 | if(s==root)return true; 137 | for(auto a : graph[s]) 138 | if(lev[match[a]]==lev[s]+1 && dfs(match[a])) 139 | return match[s]=a,match[a]=s,true; 140 | return lev[s]=M,false; 141 | } 142 | int max_matching() // match array based on [1,n+m] so keep in mind 143 | { 144 | fill(all(match),root); 145 | int ans=0; 146 | while(bfs()) 147 | for(int i=1;i<=n;i++) 148 | if(match[i]==root && dfs(i))ans++; 149 | return ans; 150 | } 151 | }; 152 | ii v[N][N]; 153 | char ans[N][N]; 154 | int I[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 155 | char ar[4]={'U','D','L','R'}; 156 | void call() 157 | { 158 | out(-1); 159 | exit(0); 160 | } 161 | void solve() 162 | { 163 | int n,i,j,a,b,x,y,c,k; 164 | set st; 165 | in(n); 166 | in4(c,a,b,x); 167 | fone(i,n) 168 | { 169 | fone(j,n) 170 | inp(v[i][j]),st.insert(v[i][j]); 171 | } 172 | bipartite_matching space(n*n,n*n); 173 | for(auto itr=st.begin();itr!=st.end();++itr) 174 | { 175 | tie(x,y)=(*itr); 176 | rep(k,4) 177 | { 178 | a=x+I[k][0],b=y+I[k][1]; 179 | if(st.find({a,b})==st.end()) 180 | continue; 181 | if((x+y)&1) 182 | space.add_edge(n*a+b-n,n*x+y-n); 183 | else 184 | space.add_edge(n*x+y-n,n*a+b-n); 185 | } 186 | } 187 | space.max_matching(); 188 | fone(i,n) 189 | { 190 | fone(j,n) 191 | { 192 | if(space.match[n*i+j-n]==0) 193 | continue; 194 | k=space.match[n*i+j-n]-n*n; 195 | x=((k-1)/n)+1,y=((k-1)%n)+1; 196 | rep(k,4) 197 | { 198 | a=x+I[k][0],b=y+I[k][1]; 199 | if(a==i && b==j) 200 | ans[i][j]=ar[k],ans[x][y]=ar[k^1]; 201 | } 202 | } 203 | } 204 | for(auto itr=st.begin();itr!=st.end();++itr) 205 | { 206 | tie(x,y)=(*itr); 207 | if(ans[x][y]==0) 208 | call(); 209 | queue pq; 210 | pq.push({x,y}); 211 | while(!pq.empty()) 212 | { 213 | tie(a,b)=pq.front(),pq.pop(); 214 | rep(k,4) 215 | { 216 | i=a+I[k][0],j=b+I[k][1]; 217 | if(v[i][j]==make_pair(x,y) && ans[i][j]==0) 218 | ans[i][j]=ar[k],pq.push({i,j}); 219 | } 220 | } 221 | } 222 | fone(i,n) 223 | { 224 | fone(j,n) 225 | if(ans[i][j]==0)call(); 226 | } 227 | llout(n*n*c); 228 | fone(i,n) 229 | { 230 | fone(j,n) 231 | cout << ans[i][j]; 232 | lin; 233 | } 234 | } 235 | void starting() 236 | { 237 | 238 | } 239 | int main() 240 | { 241 | int t=1; 242 | // in(t); 243 | starting(); 244 | while(t--) 245 | solve(); 246 | } 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /Code(java).java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | 4 | public class Main { 5 | 6 | static enum Direction { 7 | U, 8 | D, 9 | L, 10 | R 11 | } 12 | 13 | static class Cell { 14 | final int row; 15 | final int col; 16 | 17 | Direction direction = null; 18 | 19 | final int endCycleRow; 20 | final int endCycleCol; 21 | 22 | public Cell(int row, int col, int endCycleRow, int endCycleCol) { 23 | this.row = row; 24 | this.col = col; 25 | this.endCycleRow = endCycleRow; 26 | this.endCycleCol = endCycleCol; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | Cell cell = (Cell) o; 34 | return row == cell.row && 35 | col == cell.col; 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | return Objects.hash(row, col); 41 | } 42 | } 43 | 44 | private static List findCycledToItselfCells(Cell[][] matrix) { 45 | List cells = new ArrayList<>(); 46 | for (Cell[] row : matrix) { 47 | for (Cell cell : row) { 48 | if (cell.row == cell.endCycleRow && cell.col == cell.endCycleCol) { 49 | cells.add(cell); 50 | } 51 | } 52 | } 53 | return cells; 54 | } 55 | 56 | private static Cell leftNeighbour(Cell[][] matrix, Cell c) { 57 | return c.col > 0 ? matrix[c.row][c.col - 1] : null; 58 | } 59 | 60 | private static Cell rightNeighbour(Cell[][] matrix, Cell c) { 61 | return c.col < matrix.length - 1 ? matrix[c.row][c.col + 1] : null; 62 | } 63 | 64 | private static Cell upNeighbour(Cell[][] matrix, Cell c) { 65 | return c.row > 0 ? matrix[c.row - 1][c.col] : null; 66 | } 67 | 68 | private static Cell downNeighbour(Cell[][] matrix, Cell c) { 69 | return c.row < matrix.length - 1 ? matrix[c.row + 1][c.col] : null; 70 | } 71 | 72 | private static void joinSelfCycled(Cell[][] matrix, List cells, long pu, long pd, long pl, long pr) { 73 | boolean preferHorizontalJoin = pl + pr <= pu + pd; 74 | 75 | Set cellSet = new HashSet<>(cells); 76 | 77 | boolean removeAnyAdjacent = false; 78 | while (true) { 79 | int singleNeighbourRemoved = 0; 80 | 81 | for (Cell c : new ArrayList<>(cellSet)) { 82 | if (c.direction != null) continue; 83 | 84 | int neighboursCnt = 0; 85 | 86 | Cell left = leftNeighbour(matrix, c); 87 | if (left != null && cellSet.contains(left) && left.direction == null) { 88 | ++neighboursCnt; 89 | } else left = null; 90 | 91 | Cell right = rightNeighbour(matrix, c); 92 | if (right != null && cellSet.contains(right) && right.direction == null) { 93 | ++neighboursCnt; 94 | } else right = null; 95 | 96 | Cell up = upNeighbour(matrix, c); 97 | if (up != null && cellSet.contains(up) && up.direction == null) { 98 | ++neighboursCnt; 99 | } else up = null; 100 | 101 | Cell down = downNeighbour(matrix, c); 102 | if (down != null && cellSet.contains(down) && down.direction == null) { 103 | ++neighboursCnt; 104 | } else down = null; 105 | 106 | if (neighboursCnt == 0) return; 107 | 108 | if (neighboursCnt == 1) { 109 | if (left != null) { 110 | left.direction = Direction.R; 111 | c.direction = Direction.L; 112 | cellSet.remove(left); 113 | } else if (right != null) { 114 | right.direction = Direction.L; 115 | c.direction = Direction.R; 116 | cellSet.remove(right); 117 | } else if (up != null) { 118 | up.direction = Direction.D; 119 | c.direction = Direction.U; 120 | cellSet.remove(up); 121 | } else { 122 | down.direction = Direction.U; 123 | c.direction = Direction.D; 124 | cellSet.remove(down); 125 | } 126 | 127 | ++singleNeighbourRemoved; 128 | cellSet.remove(c); 129 | } 130 | } 131 | 132 | if (singleNeighbourRemoved > 0) continue; 133 | 134 | int cellsJoinedCnt = 0; 135 | for (Cell c : new ArrayList<>(cellSet)) { 136 | if (c.direction != null) continue; 137 | 138 | // removing from top-left corner 139 | Cell up = upNeighbour(matrix, c); 140 | Cell left = leftNeighbour(matrix, c); 141 | if ((up == null || !cellSet.contains(up)) && (left == null || !cellSet.contains(left))) { 142 | if (preferHorizontalJoin) { 143 | Cell right = rightNeighbour(matrix, c); 144 | if (right != null && cellSet.contains(right)) { 145 | Cell rightUp = upNeighbour(matrix, right); 146 | Cell rightDown = downNeighbour(matrix, right); 147 | if ((rightUp == null || !cellSet.contains(rightUp)) && (rightDown != null && cellSet.contains(rightDown)) || removeAnyAdjacent) { 148 | c.direction = Direction.R; 149 | right.direction = Direction.L; 150 | ++cellsJoinedCnt; 151 | cellSet.remove(c); 152 | cellSet.remove(right); 153 | removeAnyAdjacent = false; 154 | break; 155 | } 156 | } 157 | } else { 158 | Cell down = downNeighbour(matrix, c); 159 | if (down != null && cellSet.contains(down)) { 160 | Cell downLeft = leftNeighbour(matrix, down); 161 | Cell downRight = rightNeighbour(matrix, down); 162 | if ((downLeft == null || !cellSet.contains(downLeft)) && (downRight != null && cellSet.contains(downRight)) || removeAnyAdjacent) { 163 | c.direction = Direction.D; 164 | down.direction = Direction.U; 165 | ++cellsJoinedCnt; 166 | cellSet.remove(c); 167 | cellSet.remove(down); 168 | removeAnyAdjacent = false; 169 | break; 170 | } 171 | } 172 | } 173 | } 174 | 175 | // removing from bottom-left corner 176 | Cell down = downNeighbour(matrix, c); 177 | if ((down == null || !cellSet.contains(down)) && (left == null || !cellSet.contains(left))) { 178 | if (preferHorizontalJoin) { 179 | Cell right = rightNeighbour(matrix, c); 180 | if (right != null && cellSet.contains(right)) { 181 | Cell rightUp = upNeighbour(matrix, right); 182 | Cell rightDown = downNeighbour(matrix, right); 183 | if ((rightDown == null || !cellSet.contains(rightDown)) && (rightUp != null && cellSet.contains(rightUp)) || removeAnyAdjacent) { 184 | c.direction = Direction.R; 185 | right.direction = Direction.L; 186 | ++cellsJoinedCnt; 187 | cellSet.remove(c); 188 | cellSet.remove(right); 189 | removeAnyAdjacent = false; 190 | break; 191 | } 192 | } 193 | } else { 194 | up = upNeighbour(matrix, c); 195 | if (up != null && cellSet.contains(up)) { 196 | Cell upLeft = leftNeighbour(matrix, up); 197 | Cell upRight = rightNeighbour(matrix, up); 198 | if ((upLeft == null || !cellSet.contains(upLeft)) && (upRight != null && cellSet.contains(upRight)) || removeAnyAdjacent) { 199 | c.direction = Direction.U; 200 | up.direction = Direction.D; 201 | ++cellsJoinedCnt; 202 | cellSet.remove(c); 203 | cellSet.remove(up); 204 | removeAnyAdjacent = false; 205 | break; 206 | } 207 | } 208 | } 209 | } 210 | 211 | // removing from top-right corner 212 | up = upNeighbour(matrix, c); 213 | Cell right = rightNeighbour(matrix, c); 214 | if ((up == null || !cellSet.contains(up)) && (right == null || !cellSet.contains(right))) { 215 | if (preferHorizontalJoin) { 216 | left = leftNeighbour(matrix, c); 217 | if (left != null && cellSet.contains(left)) { 218 | Cell leftUp = upNeighbour(matrix, left); 219 | Cell leftDown = downNeighbour(matrix, left); 220 | if ((leftUp == null || !cellSet.contains(leftUp)) && (leftDown != null && cellSet.contains(leftDown)) || removeAnyAdjacent) { 221 | c.direction = Direction.L; 222 | left.direction = Direction.R; 223 | ++cellsJoinedCnt; 224 | cellSet.remove(c); 225 | cellSet.remove(left); 226 | removeAnyAdjacent = false; 227 | break; 228 | } 229 | } 230 | } else { 231 | down = downNeighbour(matrix, c); 232 | if (down != null && cellSet.contains(down)) { 233 | Cell downLeft = leftNeighbour(matrix, down); 234 | Cell downRight = rightNeighbour(matrix, down); 235 | if ((downRight == null || !cellSet.contains(downRight)) && (downLeft != null && cellSet.contains(downLeft)) || removeAnyAdjacent) { 236 | c.direction = Direction.D; 237 | down.direction = Direction.U; 238 | ++cellsJoinedCnt; 239 | cellSet.remove(c); 240 | cellSet.remove(down); 241 | removeAnyAdjacent = false; 242 | break; 243 | } 244 | } 245 | } 246 | } 247 | 248 | // removing from bottom-right corner 249 | down = downNeighbour(matrix, c); 250 | if ((down == null || !cellSet.contains(down)) && (right == null || !cellSet.contains(right))) { 251 | if (preferHorizontalJoin) { 252 | left = rightNeighbour(matrix, c); 253 | if (left != null && cellSet.contains(left)) { 254 | Cell leftUp = upNeighbour(matrix, left); 255 | Cell leftDown = downNeighbour(matrix, left); 256 | if ((leftDown == null || !cellSet.contains(leftDown)) && (leftUp != null && cellSet.contains(leftUp)) || removeAnyAdjacent) { 257 | c.direction = Direction.L; 258 | left.direction = Direction.R; 259 | ++cellsJoinedCnt; 260 | cellSet.remove(c); 261 | cellSet.remove(left); 262 | removeAnyAdjacent = false; 263 | break; 264 | } 265 | } 266 | } else { 267 | up = upNeighbour(matrix, c); 268 | if (up != null && cellSet.contains(up)) { 269 | Cell upLeft = leftNeighbour(matrix, up); 270 | Cell upRight = rightNeighbour(matrix, up); 271 | if ((upRight == null || !cellSet.contains(upRight)) && (upLeft != null && cellSet.contains(upLeft))) { 272 | c.direction = Direction.U; 273 | up.direction = Direction.D; 274 | ++cellsJoinedCnt; 275 | cellSet.remove(c); 276 | cellSet.remove(up); 277 | removeAnyAdjacent = false; 278 | break; 279 | } 280 | } 281 | } 282 | } 283 | } 284 | 285 | if (cellsJoinedCnt == 0) { 286 | if (!removeAnyAdjacent) { 287 | removeAnyAdjacent = true; 288 | } else { 289 | return; 290 | } 291 | } 292 | } 293 | } 294 | 295 | private static long countCost(Cell[][] matrix, long pu, long pd, long pl, long pr) { 296 | long result = 0; 297 | for (Cell[] row : matrix) { 298 | for (Cell cell : row) { 299 | if (cell.direction == null) return -1; 300 | switch (cell.direction) { 301 | case D: 302 | result += pd; 303 | break; 304 | case L: 305 | result += pl; 306 | break; 307 | case R: 308 | result += pr; 309 | break; 310 | case U: 311 | result += pu; 312 | break; 313 | } 314 | } 315 | } 316 | 317 | return result; 318 | } 319 | 320 | private static boolean sameCycle(Cell c1, Cell c2) { 321 | return c1.endCycleRow == c2.endCycleRow && c1.endCycleCol == c2.endCycleCol; 322 | } 323 | 324 | private static class Path implements Comparable { 325 | final LinkedHashSet visitedCells; 326 | final List directions; 327 | final Cell lastCell; 328 | final long totalSum; 329 | 330 | public Path(LinkedHashSet visitedCells, List directions, Cell lastCell, long totalSum) { 331 | this.visitedCells = visitedCells; 332 | this.directions = directions; 333 | this.lastCell = lastCell; 334 | this.totalSum = totalSum; 335 | } 336 | 337 | public Path move(Cell moveTo, Direction d, long cost) { 338 | LinkedHashSet newVisitedCells = new LinkedHashSet<>(this.visitedCells); 339 | newVisitedCells.add(moveTo); 340 | List newDirections = new ArrayList<>(this.directions); 341 | newDirections.add(d); 342 | return new Path(newVisitedCells, newDirections, moveTo, totalSum + cost); 343 | } 344 | 345 | public static Path forCell(Cell c) { 346 | LinkedHashSet visitedCells = new LinkedHashSet<>(); 347 | visitedCells.add(c); 348 | return new Path(visitedCells, new ArrayList<>(), c,0); 349 | } 350 | 351 | public int compareTo(Path p) { 352 | return compareResults(totalSum, directions.size(), p.totalSum, p.directions.size()); 353 | } 354 | } 355 | 356 | private static Cell chooseAnyNonVisited(Set cellsToJoin) { 357 | for (Cell c : cellsToJoin) { 358 | return c; 359 | } 360 | return null; 361 | } 362 | 363 | private static long gcd(long a, long b) { 364 | return b == 0 ? a : gcd(b, a % b); 365 | } 366 | 367 | private static long lcm(long a, long b) { 368 | return a * (b / gcd(a, b)); 369 | } 370 | 371 | private static int compareResults(long sum1, long count1, long sum2, long count2) { 372 | if (count1 == 0 || count2 == 0) return 0; 373 | long commonCount = lcm(count1, count2); 374 | return Long.compare(sum1 * (commonCount) / count1, sum2 * (commonCount) / count2); 375 | } 376 | 377 | private static void trySmartJoinCellToCycles(Cell[][] matrix, Cell cycleEndpoint, List cellsToJoin, long pu, long pd, long pl, long pr) { 378 | long minCost = Math.min(Math.min(pu, pd), Math.min(pl, pr)); 379 | Set cellsToJoinSet = new HashSet<>(cellsToJoin); 380 | 381 | 382 | while (!cellsToJoinSet.isEmpty()) { 383 | PriorityQueue paths = new PriorityQueue<>(); 384 | Path bestCandidate = null; 385 | 386 | for (Cell startCell : cellsToJoinSet) { 387 | paths.add(Path.forCell(startCell)); 388 | } 389 | 390 | while (!paths.isEmpty()) { 391 | Path path = paths.poll(); 392 | if (bestCandidate != null) { 393 | if (path.directions.size() > 0) { 394 | if (compareResults( 395 | bestCandidate.totalSum, 396 | bestCandidate.directions.size(), 397 | path.totalSum + (cellsToJoinSet.size() - path.directions.size()) * minCost, 398 | cellsToJoinSet.size()) <= 0) { 399 | continue; 400 | } 401 | } 402 | } 403 | 404 | if (path.lastCell.direction != null) { 405 | if (bestCandidate == null || path.compareTo(bestCandidate) < 0) { 406 | bestCandidate = path; 407 | } 408 | continue; 409 | } 410 | 411 | Cell up = upNeighbour(matrix, path.lastCell); 412 | if (up != null && sameCycle(up, cycleEndpoint) && !path.visitedCells.contains(up)) { 413 | paths.add(path.move(up, Direction.U, pu)); 414 | } 415 | 416 | Cell down = downNeighbour(matrix, path.lastCell); 417 | if (down != null && sameCycle(down, cycleEndpoint) && !path.visitedCells.contains(down)) { 418 | paths.add(path.move(down, Direction.D, pd)); 419 | } 420 | 421 | Cell left = leftNeighbour(matrix, path.lastCell); 422 | if (left != null && sameCycle(left, cycleEndpoint) && !path.visitedCells.contains(left)) { 423 | paths.add(path.move(left, Direction.L, pl)); 424 | } 425 | 426 | Cell right = rightNeighbour(matrix, path.lastCell); 427 | if (right != null && sameCycle(right, cycleEndpoint) && !path.visitedCells.contains(right)) { 428 | paths.add(path.move(right, Direction.R, pr)); 429 | } 430 | } 431 | 432 | if (bestCandidate == null) { 433 | return; 434 | // should never happen 435 | } 436 | 437 | List visitedCells = new ArrayList<>(bestCandidate.visitedCells); 438 | for (int i = 0; i < bestCandidate.directions.size(); ++i) { 439 | visitedCells.get(i).direction = bestCandidate.directions.get(i); 440 | cellsToJoinSet.remove(visitedCells.get(i)); 441 | } 442 | } 443 | } 444 | 445 | private static void joinCellsToCycles(Cell[][] matrix, List cycleEndpoints, long pu, long pd, long pl, long pr) { 446 | for (Cell cycleEndpoint : cycleEndpoints) { 447 | 448 | Set visited = new HashSet<>(); 449 | for (Cell[] row : matrix) { 450 | for (Cell c : row) { 451 | if (visited.contains(c) || !sameCycle(cycleEndpoint, c) || c.direction != null) { 452 | visited.add(c); 453 | continue; 454 | } 455 | 456 | Set cellsToJoin = new HashSet<>(); 457 | 458 | List currentCells = new ArrayList<>(); 459 | currentCells.add(c); 460 | cellsToJoin.add(c); 461 | visited.add(c); 462 | 463 | boolean targetMet = false; 464 | while (!currentCells.isEmpty()) { 465 | Set newCells = new HashSet<>(); 466 | for (Cell currentCell : currentCells) { 467 | List neighbours = new ArrayList<>(); 468 | 469 | Cell up = upNeighbour(matrix, currentCell); 470 | if (up != null && sameCycle(up, cycleEndpoint)) neighbours.add(up); 471 | Cell down = downNeighbour(matrix, currentCell); 472 | if (down != null && sameCycle(down, cycleEndpoint)) neighbours.add(down); 473 | Cell left = leftNeighbour(matrix, currentCell); 474 | if (left != null && sameCycle(left, cycleEndpoint)) neighbours.add(left); 475 | Cell right = rightNeighbour(matrix, currentCell); 476 | if (right != null && sameCycle(right, cycleEndpoint)) neighbours.add(right); 477 | 478 | for (Cell neighbour : neighbours) { 479 | if (neighbour.direction == null && !visited.contains(neighbour)) { 480 | newCells.add(neighbour); 481 | } 482 | if (neighbour == cycleEndpoint) targetMet = true; 483 | visited.add(neighbour); 484 | } 485 | } 486 | cellsToJoin.addAll(newCells); 487 | currentCells = new ArrayList<>(newCells); 488 | } 489 | 490 | if (!targetMet) return; 491 | 492 | if (!cellsToJoin.isEmpty()) { 493 | trySmartJoinCellToCycles(matrix, cycleEndpoint, new ArrayList<>(cellsToJoin), pu, pd, pl, pr); 494 | } 495 | } 496 | } 497 | 498 | 499 | } 500 | } 501 | 502 | static long solve(Cell[][] matrix, long pu, long pd, long pl, long pr) { 503 | List cycledToItselfCells = findCycledToItselfCells(matrix); 504 | joinSelfCycled(matrix, cycledToItselfCells, pu, pd, pl, pr); 505 | 506 | for (Cell c : cycledToItselfCells) { 507 | if (c.direction == null) return -1; 508 | } 509 | 510 | joinCellsToCycles(matrix, cycledToItselfCells, pu, pd, pl, pr); 511 | 512 | return countCost(matrix, pu, pd, pl, pr); 513 | } 514 | 515 | public static void main(String[] params) throws IOException { 516 | InputReader in = new InputReader(System.in); 517 | 518 | int n = in.readInt(); 519 | int pu = in.readInt(); 520 | int pl = in.readInt(); 521 | int pd = in.readInt(); 522 | int pr = in.readInt(); 523 | 524 | Cell[][] matrix = new Cell[n][n]; 525 | for (int i = 0; i < n; ++i) { 526 | int[] endpoints = new int[2 * n]; 527 | in.readIntArray(endpoints, 0, endpoints.length); 528 | for (int j = 0; j < n; j++) { 529 | matrix[i][j] = new Cell(i, j, endpoints[j * 2] - 1, endpoints[j * 2 + 1] - 1); 530 | } 531 | } 532 | 533 | long cost = solve(matrix, pu, pd, pl, pr); 534 | 535 | if (cost > 0) { 536 | printResult(matrix, cost); 537 | } else { 538 | System.out.println("-1"); 539 | } 540 | } 541 | 542 | private static void printResult(Cell[][] m, long cost) { 543 | System.out.println(cost); 544 | for (int i = 0; i < m.length; ++i) { 545 | for (int j = 0; j < m.length; ++j) { 546 | System.out.print(m[i][j].direction); 547 | } 548 | System.out.println(); 549 | } 550 | } 551 | 552 | static class InputReader { 553 | static final int bufferSize = 1 << 25; 554 | 555 | private char[] content; 556 | private int pos = 0; 557 | private int[] readTo = new int[1]; 558 | 559 | public InputReader(InputStream in) throws IOException { 560 | Reader charReader = new InputStreamReader(in); 561 | content = new char[bufferSize]; 562 | charReader.read(content, 0, content.length); 563 | charReader.close(); 564 | } 565 | 566 | public int readInt() { 567 | readIntArray(readTo, 0, 1); 568 | return readTo[0]; 569 | } 570 | 571 | public void readIntArray(int[] arr, int from, int length) { 572 | for (int i = from, k = 0; k < length; ++k, ++i) { 573 | while (pos < content.length && content[pos] < '0' && content[pos] != '+' && content[pos] != '-') ++pos; 574 | 575 | int num = 0; 576 | int sign = 1; 577 | if (content[pos] == '-') { 578 | sign = -1; 579 | ++pos; 580 | } else if (content[pos] == '+') ++pos; 581 | 582 | while (pos < content.length) { 583 | char ch = content[pos++]; 584 | if (ch < '0') { 585 | break; 586 | } else { 587 | int digit = ch - '0'; 588 | num = (num << 3) + (num << 1) + digit; 589 | } 590 | } 591 | arr[from++] = num * sign; 592 | } 593 | } 594 | } 595 | } --------------------------------------------------------------------------------