Kuo's Blog

競程筆記|個人網站

題目連結

d075: Q-6-10. 置物櫃出租

我的想法

我用子集合的方式,如:ZeroJudge a522,求出可退房間的數量,最後從 S 開始往上找是否有可退房數量的房間數。

參考解答

d075
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
#include <bits/stdc++.h>
#define ouo ios_base::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define db double
using namespace std;

int main() {
int n, M, S;
cin >> n >> M >> S;
int c[n], sum = 0;
for (int i = 0; i < n; i++) {
cin >> c[i];
sum += c[i];
}

bool h[M + 1] = {false};
h[0] = true;
for (int i = 0; i < n; i++) {
bool check[M + 1] = {false};
for (int j = 0; j <= M; j++) {
if (h[j] && !check[j]) {
// 這裡是預防連續兩位客人占用的房間一樣
// 所以會扣 6% 的隱藏測資
if (h[j + c[i]] == true) {
continue;
}
h[j + c[i]] = true;
check[j + c[i]] = true;
}
}
}
// S - (M - sum) 有可能為負數
// 所以會扣 7% 的隱藏測資
int x = S - (M - sum);
if (x < 0) x = 0;
for (int i = x; i <= M; i++) {
if (h[i]) {
cout << i << "\n";
break;
}
}
return 0;
}

題目連結

e287. 機器人的路徑

我的想法

純屬 BFS

參考解答

e287
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
#include <bits/stdc++.h>
#define ouo ios_base::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define db double
#define MN_const 1000001
using namespace std;

int n, m;
int x = 0, y = 0;
int G[105][105];
bool visit[105][105] = {false};
int mn = MN_const;
int ans = 0;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> G[i][j];
if (G[i][j] < mn) {
x = i;
y = j;
mn = G[i][j];
}
}
}

// set boundary
for (int i = 0; i <= n; i++) visit[i][0] = visit[i][m + 1] = true;
for (int i = 0; i <= m; i++) visit[0][i] = visit[n + 1][i] = true;

while (true) {
int nx, ny;
int d_mn = MN_const;
ans += G[x][y];
visit[x][y] = true;
for (int i = 0; i < 4; i++) {
int ix = x + dx[i], iy = y + dy[i];
if (G[ix][iy] < d_mn && visit[ix][iy] == false) {
nx = ix;
ny = iy;
d_mn = G[ix][iy];
}
}
if (d_mn == MN_const) break;
x = nx;
y = ny;
}
cout << ans << "\n";
return 0;
}

題目連結

j125. 4. 蓋步道

我的想法

尋找高度差的最小值,但線性搜尋會爆,所以用二分搜,找到此最大高度的最小值後再跑一次 BFS 算路徑長度。

參考解答

j125
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
#include <bits/stdc++.h>
#define ouo ios_base::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define db double
using namespace std;

int n;
int high = -1, low = 0;
int g[305][305];
int viewed[305][305];
queue<pair<pair<int, int>, int>> todo;
int dir[4][2] = {
{0, 1},
{0, -1},
{1, 0},
{-1, 0}
};

int bin_s(int m) {
todo.push(make_pair(make_pair(0, 0), 0));
viewed[0][0] = 1;
while (!todo.empty()) {
int x = todo.front().first.first;
int y = todo.front().first.second;
int cnt = todo.front().second;
viewed[x][y] = 1;
todo.pop();
if (x == n - 1 && y == n - 1) {
return cnt;
}
for (int i = 0; i < 4; i++) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if (nx >= 0 && nx <= n - 1 && ny >= 0 && ny <= n - 1 && viewed[nx][ny] == 0) {
int h = abs(g[x][y] - g[nx][ny]);
if (h <= m) {
viewed[nx][ny] = 1;
todo.push(make_pair(make_pair(nx, ny), cnt + 1));
}
}
}
}
return -1;
}

int main() {
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> g[i][j];
high = max(g[i][j], high);
}
}

// find h
while (high - low > 1) {
// queue.clear()
while (!todo.empty()) todo.pop();
// viewed init
memset(viewed, 0, sizeof(viewed));

int m = low + (high - low) / 2;
int check = bin_s(m);
if (check == -1) {
low = m;
} else {
high = m;
}
}
cout << high << "\n";

// print step
// queue.clear()
while (!todo.empty()) todo.pop();
// viewed init
memset(viewed, 0, sizeof(viewed));
cout << bin_s(high);

return 0;
}

題目連結

a013. 羅馬數字

我的想法

要注意的地方就是 4、9、40、90、400、900,這幾個數字都要用減法規則讀入或輸出

參考解答

a290
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
#include <bits/stdc++.h>
#define ouo ios_base::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define db double
using namespace std;

unordered_map<char, int> mp = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000}};

unordered_map<int, char> re_mp = {
{1, 'I'},
{5, 'V'},
{10, 'X'},
{50, 'L'},
{100, 'C'},
{500, 'D'},
{1000, 'M'}};

int int_mp[7] = {1, 5, 10, 50, 100, 500, 1000};

string s1, s2;

int solve(string s) {
int n = mp[s[0]];
for (int i = 1; i < s.length(); i++) {
n += mp[s[i]];
if (mp[s[i]] > mp[s[i - 1]]) {
n -= mp[s[i - 1]] * 2;
}
}
return n;
}

int main() {
ouo;

while (cin >> s1) {
if (s1 == "#") break;
cin >> s2;

int n1 = solve(s1);
int n2 = solve(s2);
int n3 = abs(n1 - n2);
if (n3 == 0) {
cout << "ZERO\n";
continue;
}

deque<char> ans;
int power = 0;
while (n3 != 0) {
int tmp = (n3 % 10) * pow(10, power);
switch (tmp) {
case 4:
ans.push_front(re_mp[tmp + 1]);
ans.push_front(re_mp[1]);
break;
case 9:
ans.push_front(re_mp[tmp + 1]);
ans.push_front(re_mp[1]);
break;
case 40:
ans.push_front(re_mp[tmp + 10]);
ans.push_front(re_mp[10]);
break;
case 90:
ans.push_front(re_mp[tmp + 10]);
ans.push_front(re_mp[10]);
break;
case 400:
ans.push_front(re_mp[tmp + 100]);
ans.push_front(re_mp[100]);
break;
case 900:
ans.push_front(re_mp[tmp + 100]);
ans.push_front(re_mp[100]);
break;
default:
deque<char> str_tmp;
for (int i = 6; i >= 0; i--) {
while (tmp / int_mp[i] > 0) {
str_tmp.push_back(re_mp[int_mp[i]]);
tmp -= int_mp[i];
}
}
for (int i = str_tmp.size() - 1; i >= 0; i--) {
ans.push_front(str_tmp[i]);
}
break;
}
power++;
n3 /= 10;
}
for (auto i : ans) {
cout << i;
}
cout << "\n";
}
return 0;
}

題目連結

d784. 一、連續元素的和

參考解法

第二次解 2023/05/27

d784
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
#include <bits/stdc++.h>
#define ouo ios_base::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define db double
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int data[n];
int mx = -INT_MAX;
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> data[i];
sum += data[i];
mx = max(mx, sum);
if (sum < 0) sum = 0;
}
cout << mx << "\n";
}
return 0;
}

第一次解

d784
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
#include <iostream>
using namespace std;

int main() {
int n1;
cin >> n1;

while (n1--) {
int n2;
cin >> n2;
int data[n2];
for (int i = 0; i < n2; i++) {
cin >> data[i];
}

int sum = data[0], max_sum = data[0];
for (int i = 1; i < n2; i++) {
if (sum < 0) sum = 0;
sum += data[i];
if (sum > max_sum) max_sum = sum;
}

cout << max_sum << "\n";
}
return 0;
}

基本介紹

定義

  • 父節點的左子節點(left node)皆小於父節點。
  • 父節點的右子節點(right node)皆大於父節點。
  • 任意節點的左右子樹都符合 BST 的定義。
  • 不存在等值的資料。

圖例:

Imgur

時間複雜度

演算法 平均 最差
空間 O(n) O(n)
搜尋 O(log n) O(n)
插入 O(log n) O(n)
刪除 O(log n) O(n)

了解更多點我

實作

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
#include <iostream>
using namespace std;

struct Node {
int data;
struct Node* left;
struct Node* right;
};

// 中序
void inorder(Node* root) {
if (root != NULL) {
inorder(root->left);
cout << root->data << " ";
inorder(root->right);
}
}

Node* add_node(Node* new_node, int n) {
if (new_node == NULL) {
new_node = new Node;
new_node->data = n;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
}
return new_node;
}

// BST 的遞迴
Node* input_data(Node* btree, int n) {
if (btree == NULL) {
btree = add_node(btree, n);
}

if (n < btree->data) {
btree->left = input_data(btree->left, n);
} else if (n > btree->data) {
btree->right = input_data(btree->right, n);
}

return btree;
}

int main() {
Node* binary_tree = NULL;
int n;
while (cin >> n) {
if (n == -1) break;
binary_tree = input_data(binary_tree, n);
}
inorder(binary_tree);
return 0;
}