# 110CP2 ## Final ```c= #include <iostream> #include <cstdlib> #include <utility> #include <string> #include <vector> #include <queue> using namespace std; int Round, M, N; char grid[20][20]={}; #define RIGHT 0 #define DOWN 1 #define UP 2 #define LEFT 3 int steps[4][2] = { {0,1}, {1,0}, {-1,0}, {0,-1} }; struct cell{ int dir; int pts; int i; int j; int count; }; struct cell cache[20][20] = {}; queue<struct cell> que; bool valid(int x, int y){ return ( x >= 0 && x < M && y >=0 && y < N && grid[x][y] != 'x' && grid[x][y] != 'A' && grid[x][y] != 'B' ); } int calculateScore(int currentScore, int i, int j) { char gettingObject = grid[i][j]; switch (gettingObject) { case 'm': return currentScore + 1; case 'n': return currentScore - 1; case 's': return currentScore * 2; case 't': return currentScore / 2; case '.': case 'b': default: return currentScore; } } string defaultOutput(int dir) { switch (dir) { case UP: return "UP"; case DOWN: return "DOWN"; case LEFT: return "LEFT"; case RIGHT: return "RIGHT"; } return "FALSE"; } string next_dir(int ci, int cj, int point) { struct cell u, d, l, r; u.i = ci + steps[2][0], u.j = cj + steps[2][1], u.dir = UP, u.count = 1; d.i = ci + steps[1][0], d.j = cj+ steps[1][1], d.dir = DOWN, d.count = 1; l.i = ci + steps[3][0], l.j = cj + steps[3][1], l.dir = LEFT, l.count = 1; r.i = ci + steps[0][0], r.j = cj + steps[0][1], r.dir = RIGHT, r.count = 1; if (valid(l.i, l.j)) { l.pts = calculateScore(point, l.i, l.j); que.push(l); } if (valid(r.i, r.j)) { r.pts = calculateScore(point, r.i, r.j); que.push(r); } if (valid(u.i, u.j)) { u.pts = calculateScore(point, u.i, u.j); que.push(u); } if (valid(d.i, d.j)) { d.pts = calculateScore(point, d.i, d.j); que.push(d); } while(!que.empty()){ struct cell deq = que.front(); que.pop(); if(cache[deq.i][deq.j].pts < deq.pts) cache[deq.i][deq.j] = deq; if(deq.count < 5) { for(int i = 0; i < 4; i++){ int next_i = deq.i+steps[i][0]; int next_j = deq.j+steps[i][1]; if(valid(next_i, next_j)) { struct cell next; next.dir = deq.dir; next.count = deq.count+1; next.i = next_i; next.j = next_j; que.push(next); } } } } int max = 0; int max_dir; for(int i = 0; i < N; i++){ for(int j = 0; j < N; j++){ if(cache[i][j].pts > max){ max = cache[i][j].pts; max_dir = cache[i][j].dir; } } } return defaultOutput(max_dir); } // cahce[i][j] = max point can be reached within 3 steps int main(void){ int A, B; char me; int ai, aj, bi, bj; cin >> Round >> M >> N; for(int i=0;i<M;i++) for(int j=0;j<N;j++) { cin >> grid[i][j]; if(grid[i][j] == 'A') ai = i, aj = j; else if(grid[i][j] == 'B') bi = i, bj = j; } cin >> A >> B >> me; if(me == 'A') cout << next_dir(ai, aj, A) << endl; else cout << next_dir(bi, bj, B) << endl; } ``` ## Cat #### solution1: without malloc ```c= #include <stdio.h> #include <stdlib.h> #include <string.h> int steps[4][2] = { {0,1}, {1,0}, {0,-1}, {-1,0} }; typedef struct cell { int x; int y; int count; } cell; void enqueue(cell queue[1000000], cell elem, int* rear) { queue[*rear] = elem; (*rear)++; } cell dequeue(cell queue[1000000], int* front) { (*front)++; return queue[*front-1]; } int bfs(char grid[100][100], int n) { cell queue[1000000]; int front = 0, rear = 1; cell start; // find start point for(int i = 0; i < n; i++) for(int j = 0; grid[i][j] != 0; j++) if(grid[i][j] == 'K') { start.x = i; start.y = j; start.count = 0; break; } queue[0] = start; while(front != rear) { cell deq = dequeue(queue, &front); int x = deq.x, y = deq.y; grid[x][y] = '#'; for(int i = 0; i < 4; i++) { int nextX = x + steps[i][0]; int nextY = y + steps[i][1]; if(nextX >= 0 && nextX < 100 && nextY >= 0 && nextY <100) { if(grid[nextX][nextY] == '.') { cell next = (cell){nextX, nextY, deq.count+1}; enqueue(queue, next, &rear); } else if (grid[nextX][nextY] == '@') return deq.count+1; } } } return 0; } int main() { int n; while(scanf("%d", &n) && n > 0) { char grid[100][100] = {'0'}; for(int i = 0; i < n; i++) scanf("%s", grid[i]); int res = bfs(grid, n); if(res) printf("%d\n", res); else printf("= =\"\n"); } return 0; } ``` #### solution2: with malloc ```c= #include <stdio.h> #include <stdlib.h> #include <string.h> int steps[4][2] = { {0,1}, {1,0}, {0,-1}, {-1,0} }; typedef struct cell { int x; int y; int count; } cell; void enqueue(cell** queue, cell* elem, int* rear) { queue[*rear] = elem; (*rear)++; } cell* dequeue(cell** queue, int* front) { (*front)++; return queue[*front-1]; } int bfs(char grid[101][101], int n) { cell* queue[1000000]; int front = 0, rear = 1; cell* start = (cell*)malloc(sizeof(cell)); // find start point for(int i = 0; i < n; i++) { for(int j = 0; grid[i][j] < 100; j++) { if(grid[i][j] == 'K') { start->x = i; start->y = j; start->count = 0; } } } queue[0] = start; while(front != rear) { cell* deq = dequeue(queue, &front); int x = deq->x, y = deq->y; grid[x][y] = '#'; for(int i = 0; i < 4; i++) { int nextX = x + steps[i][0]; int nextY = y + steps[i][1]; if(nextX >= 0 && nextX < 100 && nextY >= 0 && nextY <100) { if(grid[nextX][nextY] == '.') { cell* next = (cell*)malloc(sizeof(cell)); next->x = nextX; next->y = nextY; next->count = deq->count+1; enqueue(queue, next, &rear); } else if (grid[nextX][nextY] == '@') { int res = deq->count+1; while(front != rear) free(dequeue(queue, &front)); free(deq); return res; } } } free(deq); } return 0; } int main() { int n; while(scanf("%d", &n) && n > 0) { char grid[101][101] = {'#'}; for(int i = 0; i < n; i++) { scanf("%s", grid[i]); } int res = bfs(grid, n); if(res) printf("%d\n", res); else printf("= =\"\n"); } return 0; } ``` ## [LIS](https://leetcode.com/problems/longest-increasing-subsequence/) Given an integer array nums, return the length of the longest strictly increasing subsequence. A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7]. 解法一:`n^2` 建立一個dp array,`dp[i]`代表的是以`nums[i]`做為結尾的seq的最大長度,做法是搜尋 `dp[0]` ~ `dp[i-1]`,比對相對應的nums然後更新`dp[i]`。 ```c int lengthOfLIS(int* nums, int numsSize){ int dp[numsSize]; int max = 1; for(int i = 0; i < numsSize; i++) { dp[i] = 1; for(int j = 0; j < i; j++) dp[i] = (nums[i]>nums[j] && dp[i] <= dp[j]) ? dp[j]+1: dp[i]; max = dp[i]>max ? dp[i] : max; } return max; } ``` 解法二: `nlogn` 建立一個dp array,`dp[i]`代表的是長度i的最佳結尾,關於最佳結尾,可以思考 `1,2,3` 和 `1,2,5`誰對於這個題目來說更有未來,肯定是前者吧因為之後出現`4`後者的長度不會再增加了,前者卻可以變成`1,2,3,4`。每個新插入的數只有兩種可能 * 如果比目前`dp[-1]`(最後一個)大,可以直接串上, e.g., `1,2,3`--插入4-->`1,2,3,4` * 如果比`dp[-1]`小,就用bs更新dp, e.g., `1,2,5`--插入4-->`1,2,4` 搜尋的部分參考[這題](https://leetcode.com/problems/search-insert-position/),上課講過。最後回傳dp長度即可 ```c int lengthOfLIS(int* nums, int numsSize){ int dp[numsSize]; int idx = 0; for(int i = 0; i < numsSize; i++) { if(!idx || (dp[idx-1] < nums[i])) { dp[idx] = nums[i]; idx++; } else { int l = 0, r = idx-1; while(l <= r) { int mid = (l+r) >> 1; if(dp[mid] >= nums[i]) r = mid-1; else l = mid+1; } dp[l] = nums[i]; } } return idx; } ``` ## [minimum-number-of-removals-to-make-mountain-array](https://leetcode.com/problems/minimum-number-of-removals-to-make-mountain-array/) * 移除最少數字=計算最大長度 * 以`nums[i]`為山頂的mountain array,最大長度是LIS(`nums[:i+1]`)+LIS(`nums[i:]`)-1 ```c int minimumMountainRemovals(int* nums, int numsSize){ int nums_r[numsSize]; // copy and reverse from nums for(int i = 0; i < numsSize; i++) nums_r[i] = nums[numsSize-i-1]; int l2r[numsSize], r2l[numsSize]; LIS(nums, l2r, numsSize); // left to right LIS(nums_r, r2l, numsSize); int max = 0; for(int i = 0; i < numsSize; i++) if(l2r[i]>=2 && r2l[numsSize-i-1]>=2) max = l2r[i]+r2l[numsSize-i-1]-1 > max ? l2r[i]+r2l[numsSize-i-1]-1 : max; return numsSize-max; } void LIS(int* nums, int* maxLens, int numsSize){ int dp[numsSize]; int idx = 0; for(int i = 0; i < numsSize; i++) { if(!idx || (dp[idx-1] < nums[i])) { dp[idx] = nums[i]; idx++; } else { int l = 0, r = idx-1; while(l <= r) { int mid = (l+r) >> 1; if(dp[mid] >= nums[i]) r = mid-1; else l = mid+1; } dp[l] = nums[i]; } maxLens[i] = idx; } } ```