-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
269 lines (128 loc) · 64.5 KB
/
atom.xml
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>画客koi的空间站</title>
<link href="http://example.com/atom.xml" rel="self"/>
<link href="http://example.com/"/>
<updated>2023-11-13T06:45:41.226Z</updated>
<id>http://example.com/</id>
<author>
<name>画客koi</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>最近刷的题</title>
<link href="http://example.com/posts/19fa294d.html"/>
<id>http://example.com/posts/19fa294d.html</id>
<published>2023-11-10T13:27:27.657Z</published>
<updated>2023-11-13T06:45:41.226Z</updated>
<content type="html"><![CDATA[<h2 id="LCR-083-全排列"><a href="#LCR-083-全排列" class="headerlink" title="LCR 083. 全排列"></a>LCR 083. 全排列</h2><h3 id="原题链接"><a href="#原题链接" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9WdkprdXAv">原题链接</span>]</h3><p>状态压缩</p><pre><code class="cpp">class Solution {public: vector<vector<int>> permute(vector<int>& nums) { int n = nums.size(); int m = 1 << n; vector<vector<int>>ans; function<void(int, vector<int>&)>dfs = [&](int i, vector<int>& res) { if (i == 0) { ans.push_back(res); return ; } for(int k = 0;k < n;k++) { if ((i>>k&1) > 0) { res.push_back(nums[k]); dfs(i^(1 << k), res); res.pop_back(); } } }; for(int i = 0;i < n;i++) { vector<int>res{nums[i]}; dfs((m-1)^(1<<i), res); } return ans; }};</code></pre><h2 id="926-将字符串翻转到单调递增"><a href="#926-将字符串翻转到单调递增" class="headerlink" title="926. 将字符串翻转到单调递增"></a>926. 将字符串翻转到单调递增</h2><h3 id="原题链接-1"><a href="#原题链接-1" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9mbGlwLXN0cmluZy10by1tb25vdG9uZS1pbmNyZWFzaW5nLw==">原题链接</span>]</h3><p>动态规划</p><pre><code class="cpp">class Solution {public: int minFlipsMonoIncr(string s) { int n = s.size(); int dp0 = 0, dp1 = 0; for(int i = 0;i < n;i++) { int dpOld = dp0; dp0 = dp0 + (s[i] == '0' ? 0 : 1); //上一位是0情况下是否反转0 dp1 = min(dpOld, dp1) + (s[i] == '0' ? 1 : 0); //上一位是是1的情况下是否翻转0 } return min(dp0, dp1); }};</code></pre><h2 id="2523-范围内最接近的两个质数"><a href="#2523-范围内最接近的两个质数" class="headerlink" title="2523. 范围内最接近的两个质数"></a>2523. 范围内最接近的两个质数</h2><h3 id="原题链接-2"><a href="#原题链接-2" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9jbG9zZXN0LXByaW1lLW51bWJlcnMtaW4tcmFuZ2Uv">原题链接</span>]</h3><p>枚举质数 + 二分</p><pre><code class="cpp">const int MX = 1e6;vector<int> primes;int init = []() { bool np[MX + 1]{}; for (int i = 2; i <= MX; ++i) if (!np[i]) { primes.push_back(i); for (int j = i; j <= MX / i; ++j) // 避免溢出的写法 np[i * j] = true; } primes.push_back(MX + 1); primes.push_back(MX + 1); // 保证下面下标不会越界 return 0;}();class Solution {public: vector<int> closestPrimes(int left, int right) { auto lb = lower_bound(primes.begin(), primes.end(), left) - primes.begin(); auto rb = upper_bound(primes.begin(), primes.end(), right) - primes.begin() - 1; if (lb == rb) return {-1, -1}; int ans = INT_MAX; vector<int>ret{-1, -1}; for(lb; lb < rb;lb++) { int pre = primes[lb], cur = primes[lb + 1]; if (ans > cur - pre) { ans = cur - pre; ret = {pre, cur}; } } return ret; }};</code></pre><h2 id="1358-包含所有三种字符的子字符串数目"><a href="#1358-包含所有三种字符的子字符串数目" class="headerlink" title="1358. 包含所有三种字符的子字符串数目"></a>1358. 包含所有三种字符的子字符串数目</h2><h3 id="原题链接-3"><a href="#原题链接-3" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9udW1iZXItb2Ytc3Vic3RyaW5ncy1jb250YWluaW5nLWFsbC10aHJlZS1jaGFyYWN0ZXJzLw==">原题链接</span>]</h3><p>滑动窗口</p><pre><code class="cpp">class Solution {public: int numberOfSubstrings(string s) { int n = s.size(), m = 3; unordered_map<char, int>cnt; int l = 0, ans = 0; for(auto r : s) { cnt[r]++; while(cnt.size() == m) { int x = s[l++]; if (--cnt[x] == 0) { cnt.erase(x); } } ans += l; } return ans; }};</code></pre><h2 id="2799-统计完全子数组的数目"><a href="#2799-统计完全子数组的数目" class="headerlink" title="2799. 统计完全子数组的数目"></a>2799. 统计完全子数组的数目</h2><h3 id="原题链接-4"><a href="#原题链接-4" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9jb3VudC1jb21wbGV0ZS1zdWJhcnJheXMtaW4tYW4tYXJyYXkv">原题链接</span>]</h3><p>滑动窗口</p><pre><code class="cpp">class Solution {public: int countCompleteSubarrays(vector<int>& nums) { int n = nums.size(); unordered_map<int, int>cnt; int m = unordered_set<int>{nums.begin(), nums.end()}.size(); int l = 0, ans = 0; for(auto r : nums) { cnt[r]++; while(cnt.size() == m) { int x = nums[l++]; if (--cnt[x] == 0) { cnt.erase(x); } } ans += l; } return ans; }};</code></pre><h2 id="2300-咒语和药水的成功对数"><a href="#2300-咒语和药水的成功对数" class="headerlink" title="2300. 咒语和药水的成功对数"></a>2300. 咒语和药水的成功对数</h2><h3 id="原题链接-5"><a href="#原题链接-5" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9zdWNjZXNzZnVsLXBhaXJzLW9mLXNwZWxscy1hbmQtcG90aW9ucy8=">原题链接</span>]</h3><p>排序 + 二分</p><pre><code class="cpp">class Solution {public: vector<int> successfulPairs(vector<int>& spells, vector<int>& potions, long long success) { int n = spells.size(), m = potions.size(); vector<int>ans; sort(potions.begin(), potions.end()); for(int i = 0;i < n;i++) { int l = 0, r = m; while(l < r) { int mid = l + (r - l) / 2; long long x = (long long)potions[mid] * (long long)spells[i]; if (x >= success) r = mid; else l = mid + 1; } ans.push_back(m - l); } return ans; }};</code></pre><h2 id="1004-最大连续1的个数-III"><a href="#1004-最大连续1的个数-III" class="headerlink" title="1004. 最大连续1的个数 III"></a>1004. 最大连续1的个数 III</h2><h3 id="原题链接-6"><a href="#原题链接-6" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9tYXgtY29uc2VjdXRpdmUtb25lcy1paWkv">原题链接</span>]</h3><p>滑动窗口</p><pre><code class="cpp">class Solution {public: int longestOnes(vector<int>& nums, int k) { int n = nums.size(); int l = 0, ans = 0; vector<int>cnt(2); for(int i = 0;i < n;i++) { int r = nums[i]; cnt[r]++; while(cnt[0] > k) { int x = nums[l++]; cnt[x]--; } ans = max(ans, i - l + 1); } return ans; }};</code></pre><h2 id="2741-特别的排列"><a href="#2741-特别的排列" class="headerlink" title="2741. 特别的排列"></a>2741. 特别的排列</h2><h3 id="原题链接-7"><a href="#原题链接-7" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9zcGVjaWFsLXBlcm11dGF0aW9ucy9kZXNjcmlwdGlvbi8=">原题链接</span>]</h3><p>状态压缩</p><pre><code class="cpp">class Solution { const int MOD = 1e9 + 7;public: int specialPerm(vector<int>& nums) { int n = nums.size(); int left = (1 << n) - 1; int memo[1<<n][n]; memset(memo, -1, sizeof(memo)); function<int(int, int)> dfs = [&](int left, int i) -> int { if (left == 0) return 1; int& mem = memo[left][i]; if (mem != -1) return mem; int ans = 0; for (int j = 0; j < n; ++j) { if (((left >> j) & 1) && (nums[j] % nums[i] == 0 || nums[i] % nums[j] == 0)) ans = (ans + dfs(left ^ (1 << j), j)) % MOD; } mem = ans; return ans; }; int res = 0; for (int i = 0; i < n; ++i)//排列中第一个位置填的下标直接枚举即可 res = (res + dfs(left ^ (1 << i), i)) % MOD; return res; }};</code></pre><h2 id="2925-在树上执行操作以后得到的最大分数"><a href="#2925-在树上执行操作以后得到的最大分数" class="headerlink" title="2925. 在树上执行操作以后得到的最大分数"></a>2925. 在树上执行操作以后得到的最大分数</h2><h3 id="原题链接-8"><a href="#原题链接-8" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9tYXhpbXVtLXNjb3JlLWFmdGVyLWFwcGx5aW5nLW9wZXJhdGlvbnMtb24tYS10cmVlL2Rlc2NyaXB0aW9uLw==">原题链接</span>]</h3><p>树形dp</p><pre><code class="cpp">class Solution {public: using int64 = long long; int64 maximumScoreAfterOperations(vector<vector<int>>& edges, vector<int>& values) { vector<vector<int>> g(values.size()); g[0].push_back(-1); //dummy节点 for(auto &e : edges) { int x = e[0], y = e[1]; g[x].push_back(y); g[y].push_back(x); } //x 当前节点, fa父节点 function<int64(int, int)> dfs = [&](int x, int fa) -> int64 { if(g[x].size() == 1) { return values[x]; } int64 loss = 0; for(int y : g[x]) { if(y != fa) { loss += dfs(y, x); } } return min((int64)values[x], loss); }; return accumulate(values.begin(), values.end(), 0LL) - dfs(0, -1); }};</code></pre><h2 id="2896-执行操作使两个字符串相等"><a href="#2896-执行操作使两个字符串相等" class="headerlink" title="2896. 执行操作使两个字符串相等"></a>2896. 执行操作使两个字符串相等</h2><h3 id="原题链接-9"><a href="#原题链接-9" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9hcHBseS1vcGVyYXRpb25zLXRvLW1ha2UtdHdvLXN0cmluZ3MtZXF1YWwvZGVzY3JpcHRpb24v">原题链接</span>]</h3><p>dp</p><pre><code class="cpp">class Solution {public: int minOperations(string s1, string s2, int x) { if (s1 == s2) return 0; vector<int> p; for (int i = 0; i < s1.size(); i++) if (s1[i] != s2[i]) p.push_back(i); if (p.size() % 2) return -1; int f0 = 0, f1 = x; for (int i = 1; i < p.size(); i++) { int new_f = min(f1 + x, f0 + (p[i] - p[i - 1]) * 2); f0 = f1; f1 = new_f; } return f1 / 2; }};</code></pre><h2 id="421-数组中两个数的最大异或值"><a href="#421-数组中两个数的最大异或值" class="headerlink" title="421. 数组中两个数的最大异或值"></a>421. 数组中两个数的最大异或值</h2><h3 id="原题链接-10"><a href="#原题链接-10" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9tYXhpbXVtLXhvci1vZi10d28tbnVtYmVycy1pbi1hbi1hcnJheS8=">原题链接</span>]</h3><p>两数之和 + 位运算</p><pre><code class="cpp">class Solution {public: int findMaximumXOR(vector<int>& nums) { int mx = *max_element(nums.begin(), nums.end()); int high_bit = mx ? 31 - __builtin_clz(mx) : -1; unordered_set<int>st; int mask = 0, ans = 0; for(int i = high_bit; i >= 0; i--) { st.clear(); mask |= 1 << i; int new_ans = ans | (1 << i); for(int num : nums) { num &= mask; if (st.find(num ^ new_ans) != st.end()) { ans = new_ans; break; } st.insert(num); } } return ans; }};</code></pre><h2 id="2935-找出强数对的最大异或值-II"><a href="#2935-找出强数对的最大异或值-II" class="headerlink" title="2935. 找出强数对的最大异或值 II"></a>2935. 找出强数对的最大异或值 II</h2><h3 id="原题链接-11"><a href="#原题链接-11" class="headerlink" title="原题链接]"></a><span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9tYXhpbXVtLXN0cm9uZy1wYWlyLXhvci1paS8=">原题链接</span>]</h3><p>两数之和 + 位运算</p><pre><code class="cpp">class Solution {public: int maximumStrongPairXor(vector<int>& nums) { sort(nums.begin(), nums.end()); int high_bit = 31 - __builtin_clz(nums.back()); unordered_map<int, int>hash; int mask = 0, ans = 0; for(int i = high_bit; i >= 0; i--) { hash.clear(); mask |= 1 << i; int new_ans = ans | (1 << i); for(int y : nums) { int mask_y = y & mask; auto it = hash.find(new_ans ^ mask_y); if (it != hash.end() and it->second * 2 >= y) { ans = new_ans; break; } hash[mask_y] = y; } } return ans; }};</code></pre>]]></content>
<summary type="html"><h2 id="LCR-083-全排列"><a href="#LCR-083-全排列" class="headerlink" title="LCR 083. 全排列"></a>LCR 083. 全排列</h2><h3 id="原题链接"><a href="#原题链接" class</summary>
</entry>
<entry>
<title>pip, go get等换源</title>
<link href="http://example.com/posts/7d05470e.html"/>
<id>http://example.com/posts/7d05470e.html</id>
<published>2023-10-24T02:52:40.596Z</published>
<updated>2023-10-24T03:04:30.897Z</updated>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>pip和go get太卡了,然后想到了去换源,以此记录以下</p><h2 id="pip"><a href="#pip" class="headerlink" title="pip"></a>pip</h2><p>国内镜像</p><pre><code class="shell">阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/豆瓣 http://pypi.douban.com/simple/清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/</code></pre><p>一键换源</p><pre><code class="shell">pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple</code></pre><p>使用还要加上一点点命令</p><pre><code class="shell">pip install torchvision --trusted-host mirrors.aliyun.com</code></pre><h2 id="go-get"><a href="#go-get" class="headerlink" title="go get"></a>go get</h2>]]></content>
<summary type="html"><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>pip和go get太卡了,然后想到了去换源,以此记录以下</p>
<h2 id="pip"><a href="#pip" class="h</summary>
<category term="go" scheme="http://example.com/categories/go/"/>
<category term="python" scheme="http://example.com/categories/go/python/"/>
<category term="go" scheme="http://example.com/tags/go/"/>
<category term="python" scheme="http://example.com/tags/python/"/>
</entry>
<entry>
<title>yalantinglib配置</title>
<link href="http://example.com/posts/8cf03069.html"/>
<id>http://example.com/posts/8cf03069.html</id>
<published>2023-10-17T09:29:23.143Z</published>
<updated>2023-10-17T09:35:48.294Z</updated>
<content type="html"><![CDATA[<h3 id="记录一下如何配置yalantinglib"><a href="#记录一下如何配置yalantinglib" class="headerlink" title="记录一下如何配置yalantinglib"></a>记录一下如何配置yalantinglib</h3><p>其实很简单,但是怕忘了还是记一下</p><p>而且官方文档说的已经很详细了</p><p>首先是拉取</p><pre><code class="shell">git clone https://github.com/alibaba/yalantinglibs.git</code></pre><p>因为是hander-only,直接添加包含库就好了</p><pre><code class="c">#C++20if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines") #-ftree-slp-vectorize with coroutine cause link error. disable it util gcc fix. set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-tree-slp-vectorize")endif()#yalanting/includeinclude_directories(yalantinglibs/include)#yalanting/yltinclude_directories(yalantinglibs/include/ylt)#yalanting/third-partyinclude_directories(yalantinglibs/include/ylt/thirdparty)</code></pre><p>然后是cmake选项,因为要屏蔽一些测试</p><pre><code class="shell">cmake -DBUILD_EXAMPLES=OFF \-DBUILD_BENCHMARK=OFF \-DBUILD_UNIT_TESTS=OFF \-DINSTALL_INDEPENDENT_THIRDPARTY=ON </code></pre>]]></content>
<summary type="html"><h3 id="记录一下如何配置yalantinglib"><a href="#记录一下如何配置yalantinglib" class="headerlink" title="记录一下如何配置yalantinglib"></a>记录一下如何配置yalantinglib</h3><</summary>
<category term="C++" scheme="http://example.com/categories/C/"/>
<category term="C++" scheme="http://example.com/tags/C/"/>
</entry>
<entry>
<title>Mongodb配置(docker和cpp-driver)</title>
<link href="http://example.com/posts/9a4d6c24.html"/>
<id>http://example.com/posts/9a4d6c24.html</id>
<published>2023-10-14T04:34:44.646Z</published>
<updated>2023-10-14T04:51:57.567Z</updated>
<content type="html"><![CDATA[<h3 id="记录一下docker配置mongodb和CMake配置mongodb-cxx-driver"><a href="#记录一下docker配置mongodb和CMake配置mongodb-cxx-driver" class="headerlink" title="记录一下docker配置mongodb和CMake配置mongodb-cxx-driver"></a>记录一下docker配置mongodb和CMake配置mongodb-cxx-driver</h3><h2 id="安装docker"><a href="#安装docker" class="headerlink" title="安装docker"></a>安装docker</h2><h1 id="更新软件包"><a href="#更新软件包" class="headerlink" title="更新软件包"></a>更新软件包</h1><pre><code class="shell">sudo apt update sudo apt upgrade</code></pre><h1 id="更新Docker的依赖"><a href="#更新Docker的依赖" class="headerlink" title="更新Docker的依赖"></a>更新Docker的依赖</h1><pre><code class="shell">apt-get install ca-certificates curl gnupg lsb-release</code></pre><h1 id="添加Docker官方密钥"><a href="#添加Docker官方密钥" class="headerlink" title="添加Docker官方密钥"></a>添加Docker官方密钥</h1><pre><code class="shell">curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -</code></pre><h1 id="添加软件源"><a href="#添加软件源" class="headerlink" title="添加软件源"></a>添加软件源</h1><pre><code class="shell">sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"</code></pre><h1 id="安装Docker"><a href="#安装Docker" class="headerlink" title="安装Docker"></a>安装Docker</h1><pre><code class="shell">apt-get install docker-ce docker-ce-cli containerd.io</code></pre><h2 id="Docker配置mongodb"><a href="#Docker配置mongodb" class="headerlink" title="Docker配置mongodb"></a>Docker配置mongodb</h2><h1 id="拉取镜像"><a href="#拉取镜像" class="headerlink" title="拉取镜像"></a>拉取镜像</h1><pre><code class="shell">docker pull mongo</code></pre><h1 id="创建容器"><a href="#创建容器" class="headerlink" title="创建容器"></a>创建容器</h1><pre><code class="shell">docker run \-e MONGO_INITDB_ROOT_USERNAME=用户名 \-e MONGO_INITDB_ROOT_PASSWORD=密码 \-v /root/mongodb/data:/data/db \--name mongodb \--hostname localhost \-p 27017:27017 \--network coral \-d \mongo</code></pre><h1 id="安装OpenSSL"><a href="#安装OpenSSL" class="headerlink" title="安装OpenSSL"></a>安装OpenSSL</h1><p>记得给服务器安装ssl,详情看<span class="exturl" data-url="aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTg5MTMzNjQvY291bGQtbm90LWZpbmQtb3BlbnNzbC10cnktdG8tc2V0LXRoZS1wYXRoLXRvLW9wZW5zc2wtcm9vdC1mb2xkZXI=">https://stackoverflow.com/questions/58913364/could-not-find-openssl-try-to-set-the-path-to-openssl-root-folder</span></p><pre><code class="shell">sudo apt install libssl-dev</code></pre><h2 id="CMake配置mongodb-cxx-driver"><a href="#CMake配置mongodb-cxx-driver" class="headerlink" title="CMake配置mongodb-cxx-driver"></a>CMake配置mongodb-cxx-driver</h2><p>这东西也是配了我一个早上,记录一下</p><h1 id="克隆项目"><a href="#克隆项目" class="headerlink" title="克隆项目"></a>克隆项目</h1><pre><code class="shell">git clone https://github.com/mongodb/mongo-cxx-driver.git</code></pre><h1 id="配置CMakeList-txt"><a href="#配置CMakeList-txt" class="headerlink" title="配置CMakeList.txt"></a>配置CMakeList.txt</h1><pre><code class="c">cmake_minimum_required(VERSION 3.22.1)project(mongo_cpp)set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)add_subdirectory(third-party) #我的mongo-cxx-driver放在这里面add_executable(mongo_cpp main.cpp)target_link_libraries(mongo_cpp mongocxx_static bsoncxx_shared) #连接两个静态或者动态库</code></pre><h1 id="配置CMake变量"><a href="#配置CMake变量" class="headerlink" title="配置CMake变量"></a>配置CMake变量</h1><pre><code class="shell">cmake -DENABLE_SSL:STRING=AUTO \-DCMAKE_BUILD_TYPE=Release \-DBUILD_SHARED_AND_STATIC_LIBS=ON \-DCMAKE_INSTALL_PREFIX=/root/mongo-cpp/third-party/mongo-cxx-driver \-DBUILD_VERSION:STRING=3.8.1 \-DENABLE_TESTS=OFF \</code></pre>]]></content>
<summary type="html"><h3 id="记录一下docker配置mongodb和CMake配置mongodb-cxx-driver"><a href="#记录一下docker配置mongodb和CMake配置mongodb-cxx-driver" class="headerlink" title="记录</summary>
<category term="C++" scheme="http://example.com/categories/C/"/>
<category term="C++" scheme="http://example.com/tags/C/"/>
<category term="mongodb" scheme="http://example.com/tags/mongodb/"/>
<category term="docker" scheme="http://example.com/tags/docker/"/>
</entry>
<entry>
<title>C++快速入门教程(一)</title>
<link href="http://example.com/posts/703b66b5.html"/>
<id>http://example.com/posts/703b66b5.html</id>
<published>2023-07-15T01:44:26.000Z</published>
<updated>2023-08-01T04:50:53.277Z</updated>
<content type="html"><![CDATA[<h3 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h3><p>本系列是一个C++快速入门的教程,因此不会过分深究部分特性与细节,只是一个简单的入门教程</p><p>除此之外,如果有哪里写的不好或者出现错误的情况,或者有哪里不懂的地方,请在评论区或者QQ联系我!作者的QQ是2515579692</p><p>最后,希望观看的各位都能感受到C++的魅力</p><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><ul><li><p>C++ 是一门计算机高级程序设计语言,是C语言的一个拓展,如果有C语言基础的同学,在本篇你可以看到很多熟悉的影子…</p></li><li><p>C++ 还是一门面向对象的编程语言,至于这个面向对象是什么,我们会在下一个系列介绍。总而言之,面向对象是 C++ 的重要特性之一。</p></li><li><p>C++ 还可以进行泛型编程,但作者水平有限,还未完全掌握这方面的内容,所以目前并不会有这个方向的教程</p></li></ul><h3 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h3><h2 id="Windows系统"><a href="#Windows系统" class="headerlink" title="Windows系统"></a>Windows系统</h2><p>对于Windows系统的同学,作者在这里推荐Visual Studio作为开发环境。</p><p>进入VS的<span class="exturl" data-url="aHR0cHM6Ly92aXN1YWxzdHVkaW8ubWljcm9zb2Z0LmNvbS96aC1oYW5zLw==">官网</span>后,下拉后点击左侧的下载Visual Studio,并选择社区(Community)版</p><p><img data-src="https://s2.loli.net/2023/07/15/Wgf4tRE7O2o6QxL.png" alt="253711379-7f7b8523-1593-495a-835f-4fe9d6d345ec.png"></p><p>下载完成后,会显示这是一个下载器,我们可以根据需要的工具下载相应的开发环境。如果只是单纯的C++开发的话,只需要在这里选择“使用C++的桌面开发”和“使用C++进行Linux和嵌入式开发”即可</p><p><img data-src="https://s2.loli.net/2023/07/15/OEHveBZASwukq1G.png" alt="253712088-95d1d5a5-8e73-4a01-822b-1eccc225d028.png"></p><p><img data-src="https://s2.loli.net/2023/07/15/RyigBcZeH9Q6wbl.png" alt="253712106-26df4c5d-c5c3-4ee1-9a05-6d7dc9675bcd.png"></p><p>最后点击右下角等待安装完成即可</p><h2 id="Linux系统"><a href="#Linux系统" class="headerlink" title="Linux系统"></a>Linux系统</h2><p>对于Linux系统,Linux系统基本上是自带编译器的,我们可以用命令去查看编译器的版本</p><pre><code class="shell">gcc --versiong++ --version</code></pre><p><img data-src="https://s2.loli.net/2023/07/15/aM1EBU53emXQsd4.png" alt="253712248-2cd6fbae-a0d8-468b-95c8-59a1d3c4e42d.png"></p><p>如果出现上图的结果,则代表当前环境可以进行C/C++开发了,剩下的用vi/vim编辑器去编写代码即可。</p><h3 id="创建第一个项目"><a href="#创建第一个项目" class="headerlink" title="创建第一个项目"></a>创建第一个项目</h3><p>配置好开发环境后,我们就可以开始敲代码了,接下来我们将开始创建第一个C++项目。</p><p>首先是打开Visual Studio,然后点击右侧的创建项目</p><p><img data-src="https://s2.loli.net/2023/07/15/lDIixSrp27fQ9ZY.png" alt="253712585-cdb2ac4f-fbd5-4e4f-8572-fb1b14cbf2b4.png"></p><p>再选择空项目</p><p><img data-src="https://s2.loli.net/2023/07/15/MQUkdqxpJObHCuV.png" alt="253712615-270cab5c-2c91-4cea-980f-54cce085e0aa.png"></p><p>最后填写项目名称与项目位置,点击右下角的创建,就可以开始编程了</p><p>然后就是编写代码了,接下来我们会干一件所有入门的人都会干的事–在控制台上输出”hello world!”</p><pre><code class="cpp">#include<iostream>using namespace std;int main(){ cout << "hello world!" << endl; //在控制台上输出hello world! return 0;}</code></pre><pre><code class="shell">hello world!</code></pre><p>我们一行一行的来看这段代码。</p><p>首先是第一行,这句代码代表了我们将导入iostream这个库。在C++中,导入所需要的库通常都是以”#”开头,再接上include<库的名称>。从这个库的名称不难看出,这是一个控制输入输出流的库,里面包含了一些输入输出的函数。</p><p>然后是第三行,这句代码代表了我们需要用到用到std这个命名空间中的函数,这里再深入讲一下,所谓的命名空间,可以理解为一个工具箱,这个工具箱会包含别人库中提供的某些函数、类等。std是命名空间的名称,可以理解为这个工具箱的”生产商”,由于不同”生产商”可能会有相同名称的函数(比如华为的命名空间有一个名叫生产手机的函数,苹果的命名空间中也有一个名为生产手机的函数),这个时候我们就可以用命名空间来区分同名称但是功能可能不同的函数或者类。回到这行代码,这行代码代表了我们接下来所用到的函数、类都是来自std这个命名空间,如果不指定这句话,也可以写成这样的格式(命名空间::函数名称)</p><pre><code class="cpp">#include<iostream>int main(){ std::cout << "hello world!" << std::endl; //在控制台上输出hello world! return 0;}</code></pre><pre><code class="shell">hello world!</code></pre><p>在实际生产中,我们可能会用到来自各个命名空间的函数,所以下面这种写法会比较常见,个人也推荐慢慢习惯这种写法</p><p>然后是第五行,第五行表示了 C++ 的一个函数。特别的是,这还是一个 C++ 的入口函数,也就是说程序运行开始,就会先执行main函数中的代码。C++中,函数的格式为</p><pre><code class="cpp">返回值数据类型 函数名称(函数参数...){ 函数内容... return 返回值(可选);}</code></pre><p>函数的具体例子我们放到后面讲,现在只要知道main函数就是程序的入口即可。</p><p>再看第七行,第七行代表了我们使用std命名空间中的cout函数和endl函数在控制台上输出了”hello world!”。cout是C++中的标准输出函数,可以将”<<”后的内容输出到输出设备(控制台),与此对应的还有cin函数,可以从输入设备(键盘)中读取输入,再保存到变量中。endl是”endline”的意思,代表本行结束,换行。最后,还需要在本行的最后加上分号(;)</p><p>从上面也能看出,C++用的注释格式是 “//“ ,也可以用 “/* */“ 将一片注释包裹起来</p><pre><code class="cpp">//你说得对,但是原神是一款../*你说得对但是原神是一款.. */</code></pre><p>最后第八行是函数的返回值,main函数中返回0即可。</p><h3 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h3><p>在 C++ 中,数据的类型十分重要,如果使用了错误的类型,可能会得到意想不到的结果,甚至可能无法通过编译…</p><p>下面我们就来介绍 C++ 中最基本的一些数据类型</p><ul><li>int: 整型,用来表示整数,能表示32位整数</li><li>long long: 长整形,可以用来表示更大的整数,能表示64位整数</li><li>float: 浮点类型,可以用来表示小数</li><li>double: 双精度浮点类型,可以表示更精确的小数</li><li>char: 字符类型,用于表示一个字符</li><li>bool: 布尔类型,只有两种可能,true或者false,可以想象成一个灯只有开和关两种可能</li></ul><p>了解了这些数据类型之后,我们就可以来了解变量,常量,函数等概念了…</p><h3 id="变量与常量"><a href="#变量与常量" class="headerlink" title="变量与常量"></a>变量与常量</h3><h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><p>所谓变量,就是程序执行过程中可能会发生变化的值,定义一个变量通常的格式是(变量的数据类型 变量名称 = 初始值)</p><pre><code class="cpp">int a;int b = 3;double c = 3.01;char d = 'd';bool e = true;b = 6;b += 1;int f = b;</code></pre><p>上述代码中就定义了一些变量,我们一个一个来看。</p><ul><li>a: 一个整型,但是没有进行初始化赋值,所以如果在后续代码中使用的话,会报错</li><li>b: 也是一个整型,初始化的值为3,接下来我们就可以用b代指3</li><li>c: 一个双精度浮点类型,在这里用来表示小数3.01</li><li>d: 字符类型,表示了 ‘d’ 这个字母</li><li>e: 布尔类型,表示的值为true</li></ul><p>我们可以对变量就行修改,比如7-8行中,我们可以将b的值改为6,再进行 +1 操作,让b的值变为7。<br>我们也可以将变量</p><ul><li>ps: 可以通过cout来打印各个变量。</li></ul><h2 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h2><p>所谓常量,就是程序执行中不会发生变化的值,定义一个常量的通常格式是(const 常量的数据类型 常量名称 = 初始值)</p><pre><code class="cpp">const double pi = 3.1415926;</code></pre><p>上述代码定义了一个常量,让我们来看看</p><ul><li>pi: 定义了圆周率,显然这种数值在程序运行过程中(甚至在现实世界中)都不会发生改变,我们就可以将其设置为常量。</li></ul><p>ps:</p><ul><li>1.在程序运行过程中,不能有修改常量的行为</li><li>2.常量一定要在初始化时赋值,因为后面将无法修改</li><li>3.可以通过cout来打印各个常量</li></ul><h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h3><p>数组可以将相同类型的一堆数放在一起。请注意,这里是指<code>相同类型</code>的一堆数,不同类型是无法放进来的!以下是定义一个数组的方法</p><pre><code class="cpp">数据类型 数组名称[元素个数] = {...};</code></pre><p>光看定义还是有点抽象,现在来举个例子</p><pre><code class="cpp">int arr[5] = {1, 2, 3, 4, 5};char str[5] = {'a', 'b', 'c', 'd', 'e'};</code></pre><p>上面定义了两个数组,一个是整型数组,一个是字符数组。括号中的<code>5</code>代表数组只能存5个元素(可以不存满,但是上限为5),而上面的整型数组就存储了整型数字1<del>5,<br>字符数组存了a</del>e五个字母。</p><h2 id="索引-x2F-下标"><a href="#索引-x2F-下标" class="headerlink" title="索引/下标"></a>索引/下标</h2><p>我们可以通过下标(或者叫索引)的方式取到数组中的元素。下标从0开始,比如我们需要取到数组中<code>1</code>这个数字,而1的下标是0,所以arr[0]就是数字1, 以此类推<br>arr[1]就是2…arr[4]就是5</p>]]></content>
<summary type="html"><h3 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h3><p>本系列是一个C++快速入门的教程,因此不会过分深究部分特性与细节,只是一个简单的入门教程</p>
<p>除此之外,如果有哪里</summary>
<category term="C++" scheme="http://example.com/categories/C/"/>
<category term="C++" scheme="http://example.com/tags/C/"/>
<category term="入门教程" scheme="http://example.com/tags/%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/"/>
</entry>
<entry>
<title>Leetcode.1584连接所有点的最小费用</title>
<link href="http://example.com/posts/cee06c4e.html"/>
<id>http://example.com/posts/cee06c4e.html</id>
<published>2023-07-10T12:29:51.000Z</published>
<updated>2023-07-10T12:32:22.001Z</updated>
<content type="html"><![CDATA[<h3 id="原题链接-–-1584-连接所有点的最小费用"><a href="#原题链接-–-1584-连接所有点的最小费用" class="headerlink" title="原题链接 – [1584. 连接所有点的最小费用]"></a>原题链接 – [<span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9taW4tY29zdC10by1jb25uZWN0LWFsbC1wb2ludHMv">1584. 连接所有点的最小费用</span>]</h3><h3 id="题目概述:"><a href="#题目概述:" class="headerlink" title="题目概述:"></a>题目概述:</h3><p>Tag : 「最小生成树」</p><p><img data-src="https://user-images.githubusercontent.com/99656524/201503569-87e59ce3-8b74-4bb2-ba4e-43f772edbf55.png" alt="image"></p><p><img data-src="https://user-images.githubusercontent.com/99656524/201503584-03bb37f7-4f5e-4a20-ad72-7b47d529e5e5.png" alt="image"></p><p><img data-src="https://user-images.githubusercontent.com/99656524/201503592-4f9b34bd-44f0-4315-ac6c-e715242c0aa6.png" alt="image"></p><h3 id="解法一:Kruskal算法"><a href="#解法一:Kruskal算法" class="headerlink" title="解法一:Kruskal算法"></a>解法一:Kruskal算法</h3><p>本题是最小生成树的入门题,可以当作一个模板来看</p><p>题目大意为找出链接所有点的最小代价,十分类似于最小生成树的性质,生成树的性质如下:</p><ul><li>一个连通图可以有多个生成树;</li><li>一个连通图的所有生成树都包含相同的顶点个数和边数;</li><li>生成树当中不存在环;</li><li>移除生成树中的任意一条边都会导致图的不连通, 生成树的边最少特性;</li><li>在生成树中添加一条边会构成环。</li><li>对于包含n个顶点的连通图,生成树包含n个顶点和n-1条边;</li><li>对于包含n个顶点的无向完全图最多包含 $n^n/n^2$ 颗生成树。</li></ul><p>而最小生成树,就是在原有的图上给每条边加上权重,查找连接所有点的最小总权重</p><p>关于最小生成树,现在我了解到的只有两种算法,我们先来介绍第一种克鲁斯卡尔算法(Kruskal)<br>克鲁斯卡尔算法的思想类似于贪心</p><p>存完图之后,按照每个点的之间的权重从小到大排序,每次取出权重最小的边,将两个点连接起来,这个时候就要用到并查集这种数据结构了</p><p>并查集能够判断两个点是否有链接,有判断两个点是否连接和两个点建立连接以及找到该点的祖先等功能</p><p>当点的数量 == 边的数量 -1 的时候,说明完成了最小生成树的连接</p><p>C++代码:</p><pre><code class="cpp">//定义边class Edge{public: int start;//起始结点 int end;//终止结点 int cost;//权重 Edge(int start, int end, int cost) :start(start), end(end), cost(cost) {}};//并查集class UnionFind{public: vector<int>root; UnionFind(int n)//有n个数 { root.assign(n, 0); for (int i = 0; i < n; i++)//初始化 { root[i] = i; } } int find(int x) { return root[x] == x ? x : root[x]= find(root[x]); } void Union(int x, int y) { root[find(x)]=root[find(y)];//根节点连接 } bool connected(int x, int y)//检查是否相连 { return find(x) == find(y); }};//Kruskal Algorithm//链接所有点的最小花费class Solution{public: int minCostConnectPoints(vector<vector<int>>points) { int n = points.size(); vector<Edge>edges;//用于存储边 UnionFind uf(n);//并查集 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);//计算距离 Edge edge(i,j,cost); edges.emplace_back(edge); } } sort(edges.begin(), edges.end(), [](Edge& a, Edge& b) {return a.cost < b.cost; });//按权重从小到大排序 int res = 0; int count = 0; for (const auto& edge : edges) { if (count == n - 1) { break;//最小生成树的边要比结点少一个 } if (uf.connected(edge.start, edge.end))//若结点间已连接 { continue; } else { uf.Union(edge.start, edge.end); res += edge.cost; count++; } } return res; }};</code></pre><ul><li>时间复杂度: $O(n^2logn)$,一般 Kruskal 是 $O(mlogm)$ 的算法,但本题中 $m=n^2$ </li><li>空间复杂度: $O(n^2)$ , $O(n)$ 并查集, $O(n^2)$ 建图</li></ul><h3 id="解法二:Prim算法"><a href="#解法二:Prim算法" class="headerlink" title="解法二:Prim算法"></a>解法二:Prim算法</h3><p>普里姆算法也是求最小生成树的一种算法</p><p>普里姆在求最小生生成树的时候将点分为两类,一类是最小生成树已经包括的点(A类点),另一类是没有包括最小生成树的点(B类点),每次在A类点中找寻权重最小的边,并将边的另一个点从B类点中加入A类点,随后继续从A类点中寻找权重最小的边,直到点的数量 == 边的数量 -1 后结束。</p><p>C++代码:</p><pre><code class="cpp">//定义边class Edge{public: int start;//起始结点 int end;//终止结点 int cost;//权重 Edge(int start, int end, int cost) :start(start), end(end), cost(cost) {}};bool operator<(Edge a,Edge b){ return a.cost>b.cost;}//Prim Algorithm//链接所有点的最小花费class Solution{public: int minCostConnectPoints(vector<vector<int>>points) { int n = points.size(); priority_queue<Edge>edges; vector<bool>visited(n,0);//判断点是否已经被查询过了 for (int j = 1; j < n; j++) { int cost = abs(points[0][0] - points[j][0]) + abs(points[0][1] - points[j][1]); edges.emplace(Edge(0,j,cost)); } int res = 0; int count = n - 1; visited[0] = true; while (!edges.empty() && count > 0) { Edge e = edges.top(); edges.pop(); if (!visited[e.end]) { res += e.cost; visited[e.end] = true; for (int j = 0; j < n; j++) { if (!visited[j]) { int distance = abs(points[e.end][0] - points[j][0]) + abs(points[e.end][1] - points[j][1]); edges.emplace(Edge(e.end, j, distance)); } } count--; } } return res; }};</code></pre><ul><li>时间复杂度: $O(n^2)$</li><li>空间复杂度: $O(n^2)$</li></ul>]]></content>
<summary type="html"><h3 id="原题链接-–-1584-连接所有点的最小费用"><a href="#原题链接-–-1584-连接所有点的最小费用" class="headerlink" title="原题链接 – [1584. 连接所有点的最小费用]"></a>原题链接 – [<span cla</summary>
<category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
<category term="图论" scheme="http://example.com/tags/%E5%9B%BE%E8%AE%BA/"/>
<category term="最小生成树" scheme="http://example.com/tags/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/"/>
</entry>
<entry>
<title>Leetcode.2642设计可以求最短路径的图类</title>
<link href="http://example.com/posts/e0b5f3f4.html"/>
<id>http://example.com/posts/e0b5f3f4.html</id>
<published>2023-07-10T12:24:57.000Z</published>
<updated>2023-07-10T12:32:47.282Z</updated>
<content type="html"><![CDATA[<h3 id="原题链接-–-2642-设计可以求最短路径的图类"><a href="#原题链接-–-2642-设计可以求最短路径的图类" class="headerlink" title="原题链接 – [2642. 设计可以求最短路径的图类]"></a>原题链接 – [<span class="exturl" data-url="aHR0cHM6Ly9sZWV0Y29kZS5jbi9wcm9ibGVtcy9kZXNpZ24tZ3JhcGgtd2l0aC1zaG9ydGVzdC1wYXRoLWNhbGN1bGF0b3Iv">2642. 设计可以求最短路径的图类</span>]</h3><h3 id="题目概述:"><a href="#题目概述:" class="headerlink" title="题目概述:"></a>题目概述:</h3><p>Tag : 「最短路径」、「图」</p><p><img data-src="https://user-images.githubusercontent.com/99656524/236496650-ff3c6a0a-ac50-4ca6-9c73-0196ca0df496.png" alt="image"></p><p><img data-src="https://user-images.githubusercontent.com/99656524/236496689-e4025225-0634-456b-bd83-74f61310be3f.png" alt="image"></p><h3 id="数据范围"><a href="#数据范围" class="headerlink" title="数据范围"></a>数据范围</h3><ul><li>$1 <= n <= 100$</li><li>$0 <= edges.length <= n * (n - 1)$</li><li>$edges[i].length == edge.length == 3$</li><li>$0 <= fromi, toi, from, to, node1, node2 <= n - 1$</li><li>$1 <= edgeCosti, edgeCost <= 10^6$</li><li>$图中任何时候都不会有重边和自环。$</li><li>$调用 addEdge 至多 100 次。$</li><li>$调用 shortestPath 至多 100 次。$</li></ul><h3 id="解法一:Dijkstra算法"><a href="#解法一:Dijkstra算法" class="headerlink" title="解法一:Dijkstra算法"></a>解法一:Dijkstra算法</h3><p>一道值得学习的模板题,也很适合用来做模板</p><p>C++代码:</p><pre><code class="cpp">class Graph {public: const int inf = INT_MAX / 2; vector<vector<int>>g; int n_; Graph(int n, vector<vector<int>>& edges) { n_ = n; g = vector<vector<int>>(n, vector<int>(n, inf)); for(auto & edge : edges)g[edge[0]][edge[1]] = edge[2]; } void addEdge(vector<int> edge) { g[edge[0]][edge[1]] = edge[2]; } int shortestPath(int node1, int node2) { vector<int>dist(n_, inf); vector<int>st(n_); dist[node1] = 0; while(1) { int x = -1; for(int y = 0; y < n_; y++) { if(!st[y] and (x == -1 or dist[x] > dist[y]))x = y; } if(x < 0 or dist[x] == inf)return -1; //能遍历的点都遍历完了 if(x == node2)return dist[x]; st[x] = true; for(int y = 0; y < n_ ; y++) { dist[y] = min(dist[y], dist[x] + g[x][y]); } } }};/** * Your Graph object will be instantiated and called as such: * Graph* obj = new Graph(n, edges); * obj->addEdge(edge); * int param_2 = obj->shortestPath(node1,node2); */</code></pre><ul><li>时间复杂度: $O(qn^2)$ ,其中q为调用求最短路次数</li><li>空间复杂度: $O(n^2)$</li></ul><h3 id="解法二:堆优化Dijkstra算法"><a href="#解法二:堆优化Dijkstra算法" class="headerlink" title="解法二:堆优化Dijkstra算法"></a>解法二:堆优化Dijkstra算法</h3><pre><code class="cpp">class Graph {public: using PII = pair<int, int>; const int inf = INT_MAX / 2; vector<vector<PII>>g; int n_; Graph(int n, vector<vector<int>>& edges) { g = vector<vector<PII>>(n); n_ = n; for(auto &edge : edges) g[edge[0]].emplace_back(edge[1], edge[2]); } void addEdge(vector<int> edge) { g[edge[0]].emplace_back(edge[1], edge[2]); } int shortestPath(int node1, int node2) { vector<int>dist(n_, inf); dist[node1] = 0; priority_queue<PII, vector<PII>, greater<>>pq; pq.emplace(node1, 0); while(!pq.empty()) { auto [x, dx] = pq.top(); pq.pop(); if(dx > dist[x])continue; for(auto [y, w] : g[x]) { int dy = dist[x] + w; if(dy < dist[y]) { dist[y] = dy; pq.emplace(y, dy); } } } return dist[node2] == inf ? -1 : dist[node2]; }};/** * Your Graph object will be instantiated and called as such: * Graph* obj = new Graph(n, edges); * obj->addEdge(edge); * int param_2 = obj->shortestPath(node1,node2); */</code></pre><ul><li>时间复杂度: $O(qnlogn)$ ,其中q为调用求最短路次数</li><li>空间复杂度: $O(n + m)$ ,其中m为边的个数</li></ul><h3 id="解法三:Floyd算法"><a href="#解法三:Floyd算法" class="headerlink" title="解法三:Floyd算法"></a>解法三:Floyd算法</h3><pre><code class="cpp">class Graph {public: const int inf = INT_MAX / 3; //除以二会溢出 int n_; vector<vector<int>>f; Graph(int n, vector<vector<int>>& edges) { n_ = n; f = vector<vector<int>>(n, vector<int>(n, inf)); for(int i = 0;i < n;i++)f[i][i] = 0; //初始化 for(auto &edge : edges) f[edge[0]][edge[1]] = edge[2]; for(int k = 0;k < n;k++) { for(int i = 0;i < n;i++) { for(int j = 0;j < n;j++)f[i][j] = min(f[i][j], f[i][k] + f[k][j]); } } } void addEdge(vector<int> edge) { int x = edge[0], y = edge[1], w = edge[2]; if(w >= f[x][y])return ;//无需更新 for(int i = 0;i < n_;i++) { for(int j = 0;j < n_; j++)f[i][j] = min(f[i][j], f[i][x] + f[y][j] + w); } } int shortestPath(int node1, int node2) { int ans = f[node1][node2]; return ans == inf ? -1 : ans; }};/** * Your Graph object will be instantiated and called as such: * Graph* obj = new Graph(n, edges); * obj->addEdge(edge); * int param_2 = obj->shortestPath(node1,node2); */</code></pre><ul><li>时间复杂度: $O(n^3 + qn^2)$ ,其中q为调用加边的次数</li><li>空间复杂度: $O(n^2)$</li></ul>]]></content>
<summary type="html"><h3 id="原题链接-–-2642-设计可以求最短路径的图类"><a href="#原题链接-–-2642-设计可以求最短路径的图类" class="headerlink" title="原题链接 – [2642. 设计可以求最短路径的图类]"></a>原题链接 – [<sp</summary>
<category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
<category term="图论" scheme="http://example.com/tags/%E5%9B%BE%E8%AE%BA/"/>
</entry>
<entry>
<title>Acwing3.完全背包问题</title>
<link href="http://example.com/posts/e75ef1cc.html"/>
<id>http://example.com/posts/e75ef1cc.html</id>
<published>2023-07-10T12:07:56.000Z</published>
<updated>2023-07-10T12:14:25.656Z</updated>
<content type="html"><![CDATA[<h3 id="原题链接-–-3-完全背包问题"><a href="#原题链接-–-3-完全背包问题" class="headerlink" title="原题链接 – [3. 完全背包问题]"></a>原题链接 – [<span class="exturl" data-url="aHR0cHM6Ly93d3cuYWN3aW5nLmNvbS9wcm9ibGVtL2NvbnRlbnQvZGVzY3JpcHRpb24vMy8=">3. 完全背包问题</span>]</h3><h3 id="题目概述:"><a href="#题目概述:" class="headerlink" title="题目概述:"></a>题目概述:</h3><p>Tag : 「动态规划」</p><p><img data-src="https://user-images.githubusercontent.com/99656524/225010647-ad6ebb64-acf9-430b-a974-b7e79d489f12.png" alt="image"></p><h3 id="解法一-动态规划"><a href="#解法一-动态规划" class="headerlink" title="解法一:动态规划"></a>解法一:动态规划</h3><p>背包问题是一个系列,完全背包是这个系列的第二章,其他的<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL25hMmNvM2hrL0Fsb2dyaXRobS90cmVlL21haW4vJUU1JThBJUE4JUU2JTgwJTgxJUU4JUE3JTg0JUU1JTg4JTkyLyVFOCU4MyU4QyVFNSU4QyU4NSVFOSU5NyVBRSVFOSVBMiU5OA==">在这里</span></p><p>下面是正题</p><p>本题是01背包的一道进阶版本,唯一的改动是每件物品都可以装无限次,仍然是求能装物品价值的最大值。</p><p>和01背包一样,从递推开始想,设第i件物品的体积为v[i], 价值为w[i],设第i件物品总共选择k次,用递归的形式可以得出:</p><p>$$<br> dfs(i, V) = max(dfs(i-1, V), dfs(i-1, V-k * v[i]) + k * w[i]) ( i, V = N,N-1…2,1 )<br>$$</p><p>其中dfs(i, V)代表第i件物品选k次,重量不超过V的价值</p><p>然后转换成递推式:</p><p>$$<br> f[i,j] = max(f[i-1][j], f[i-1][j - k * v[i]] + k * w[i]) ( i, j = 1, 2, 3…N )<br>$$</p><p>这是最基本的表达式,我们可以试着像01背包那样优化一下,将数组降为一维,这样就可以得出一个基本的表达式</p><p>$$<br> f[j]=max(f[j],f[j-k * v[i]]+k * w[i]);<br>$$</p><p>C++代码:</p><pre><code class="cpp">#include<iostream>using namespace std;const int maxn = 1010;int n,m;int v[maxn],w[maxn];int dp[maxn];int main(){ cin>>n>>m; for(int i = 1;i<=n;i++) { cin>>v[i]>>w[i]; } for(int i = 1;i<=n;i++) { for(int j = 0;j<=m;j++) { for(int k = 0;k*v[i]<=j;k++ ) { dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]); } } } cout<<dp[m]; return 0;}</code></pre><ul><li>时间复杂度: $O(nm^2)$ 可能有错</li><li>空间复杂度: $O(m)$</li></ul><h3 id="优化(重点)"><a href="#优化(重点)" class="headerlink" title="优化(重点)"></a>优化(重点)</h3><p>从上面的代码可以看出,代码枚举需要用到三重循环,显然这样的时间复杂度是不能接受的,我们可以考虑优化掉一层循环。</p><p>优化总是从状态转移方程开始考虑,若将第i件物品只选择一次的表达式和原本的表达式结合在一起看,如下图所示</p><p><img data-src="https://user-images.githubusercontent.com/99656524/225027827-a2525866-1893-49e0-ae8c-3b6273312d66.png" alt="image"></p><p>从上图不难看出:</p><p>$$<br> f[i][j]=max(f[i,j-v]+w , f[i-1][j])<br>$$</p><p>这样就得到了完全背包的一个优化方程,并且这个式子和01背包的转移方程十分相识</p><p>f[i][j] = max(f[i-1][j],f[i-1][j-v[i]]+w[i]);//01背包</p><p>f[i][j] = max(f[i-1][j],f[i][j-v[i]]+w[i]);//完全背包问题</p><p>两个式子只差了一个i-1,因此完全背包也可以使用01背包的优化方法即可得出完全背包问题的最终表达式</p><p>$$<br> f[j]=max(f[j],f[j-v[i]]+w[i])<br>$$</p><p>但是这次由于是需要同一层的数据,所以直接顺序遍历即可</p><p>C++代码:</p><pre><code class="cpp">#include<iostream>using namespace std;const int maxn = 1010;int n,m;int v[maxn],w[maxn];int dp[maxn];int main(){ cin>>n>>m; for(int i = 1;i<=n;i++) { cin>>v[i]>>w[i]; } for(int i = 1;i<=n;i++) { for(int j = v[i];j<=m;j++) { dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } cout<<dp[m]; return 0;}</code></pre><ul><li>时间复杂度: $O(nm)$ 可能有错</li><li>空间复杂度: $O(m)$</li></ul>]]></content>
<summary type="html"><h3 id="原题链接-–-3-完全背包问题"><a href="#原题链接-–-3-完全背包问题" class="headerlink" title="原题链接 – [3. 完全背包问题]"></a>原题链接 – [<span class="exturl" data-url=</summary>
<category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
<category term="背包问题" scheme="http://example.com/tags/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/"/>
<category term="动态规划" scheme="http://example.com/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>Acwing2.01背包问题</title>
<link href="http://example.com/posts/f0208ea3.html"/>
<id>http://example.com/posts/f0208ea3.html</id>
<published>2023-07-10T11:53:42.000Z</published>
<updated>2023-07-10T12:13:46.394Z</updated>
<content type="html"><![CDATA[<h3 id="原题链接-–-2-01背包问题"><a href="#原题链接-–-2-01背包问题" class="headerlink" title="原题链接 – [2. 01背包问题]"></a>原题链接 – [<span class="exturl" data-url="aHR0cHM6Ly93d3cuYWN3aW5nLmNvbS9wcm9ibGVtL2NvbnRlbnQvZGVzY3JpcHRpb24vMi8=">2. 01背包问题</span>]</h3><h3 id="题目概述:"><a href="#题目概述:" class="headerlink" title="题目概述:"></a>题目概述:</h3><p>Tag : 「动态规划」</p><p><img data-src="https://user-images.githubusercontent.com/99656524/197217653-0f3c2f52-cd6e-409c-b2c3-f7ffc304695e.png" alt="image"></p><h3 id="解法一-动态规划"><a href="#解法一-动态规划" class="headerlink" title="解法一:动态规划"></a>解法一:动态规划</h3><p>背包问题是经典的动态规划类题目,很多题目也是根据背包的模型改编而成的</p><p>背包问题是一个系列,01背包是这个系列的第一章,其他的<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL25hMmNvM2hrL0Fsb2dyaXRobS90cmVlL21haW4vJUU1JThBJUE4JUU2JTgwJTgxJUU4JUE3JTg0JUU1JTg4JTkyLyVFOCU4MyU4QyVFNSU4QyU4NSVFOSU5NyVBRSVFOSVBMiU5OA==">在这里</span></p><p>下面是正题</p><p>对于动态规划问题,一个通用想法就是从递归开始想,设第i件物品的体积为v[i], 价值为w[i],由于每个物品只有选和不选两种状态,用递归的形式可以得出</p><p>$$<br> dfs(i, V) = max(dfs(i-1, V), dfs(i-1, V-v[i]) + w[i]) ( i, V = N,N-1…2,1 )<br>$$</p><p>其中</p><p>$dfs(i, V)代表前i件物品重量不超过V能够得到的最大价值$</p><p>$dfs(i-1, V)代表不选择第i件物品时不超过V能得到的最大价值$</p><p>$dfs(i-1, V-v[i]) + w[i]代表选择第i件物品时不超过V能得到的最大价值$</p><p>上述的式子也可以转换成用数组的递推式</p><p>$$<br> f[i,V] = max(f[i-1][V], f[i-1][V-v[i]] + w[i]) ( i, V = 1, 2, 3…N )<br>$$</p><p>接着就要考虑递推式的初始化问题,但是这题求的是最大值,可以直接全部默认初始化为0</p><p>最后用循环枚举各种状态,最终的状态为 f[N][V]</p><p>C++代码:</p><pre><code class="cpp">#include<iostream>using namespace std;const int MAX = 1010;int N,V;//物品数量,背包容量int v[MAX],w[MAX];//体积,价值int main(){ cin>>N>>V; for(int i = 1;i <= N;i++) { cin>>v[i]>>w[i]; } int dp[MAX+1][MAX+1]; for(int i = 1;i <= N;i++)//枚举物品数量 { for(int j = 0;j <= V;j++)//枚举背包重量 { if(j<v[i])//背包剩余重量不够 { dp[i][j]=dp[i-1][j];//只能不选 } else { dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]); } } } cout<<dp[N][V]; return 0;}</code></pre><ul><li>时间复杂度: $O(NV)$ 可能有错</li><li>空间复杂度: $O(NV)$</li></ul><h3 id="优化(重点)"><a href="#优化(重点)" class="headerlink" title="优化(重点)"></a>优化(重点)</h3><p>从上面的状态转移表达式可以看出,f[i][j]这个状态只会由f[i-1]这种状态转移过来,于是我们可以进行滚动数组优化,即将数组降低至一维。将数组去掉一维可以得到状态转移方程为:</p><p>$$<br> f[j] = max(f[j], f[j-v[i]]+w[i])<br>$$</p><p>这里还没完,如果只是单纯地改动这地方的话其实是错误的。从原本的表达式我们可以知道f[i]用的是上一层,也就是f[i-1]的数据,我们必须要保证f[i]就是由f[i-1]转移而来。因为f[j]和f[j-v[i]]都是在第i次循环计算出来的,会导致我们得到的是f[i][j-v[i]]而并非f[i-1][j-v[i]],因此我们需要将第二重循环从后往前遍历,改变一下递推的顺序,保证数据是从上一层的状态转移过来的</p><pre><code class="cpp">#include<iostream>#include<vector>using namespace std;const int MAX = 1010;int N,V;//物品数量,背包容量int v[MAX],w[MAX];//体积,价值int main(){ cin >>N>>V; for(int i = 1;i <= N;i++)cin >> v[i] >> w[i]; int dp[MAX] = { 0 }; for(int i = 1;i <= N;i++) { for(int j = V;j >= v[i];j--)dp[j] = max(dp[j], dp[j-v[i]]+w[i]); } cout << dp[V] << endl; return 0;}</code></pre><ul><li>时间复杂度: $O(NV)$ 可能有错</li><li>空间复杂度: $O(V)$</li></ul>]]></content>
<summary type="html"><h3 id="原题链接-–-2-01背包问题"><a href="#原题链接-–-2-01背包问题" class="headerlink" title="原题链接 – [2. 01背包问题]"></a>原题链接 – [<span class="exturl" data-url=</summary>
<category term="算法" scheme="http://example.com/categories/%E7%AE%97%E6%B3%95/"/>
<category term="背包问题" scheme="http://example.com/tags/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/"/>
<category term="动态规划" scheme="http://example.com/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="http://example.com/posts/4a17b156.html"/>
<id>http://example.com/posts/4a17b156.html</id>
<published>2023-07-10T05:24:28.675Z</published>
<updated>2023-07-10T05:52:24.641Z</updated>
<content type="html"><![CDATA[<p>Welcome to <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvLw==">Hexo</span>! This is your very first post. Check <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3Mv">documentation</span> for more info. If you get any problems when using Hexo, you can find the answer in <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3MvdHJvdWJsZXNob290aW5nLmh0bWw=">troubleshooting</span> or you can ask me on <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2hleG9qcy9oZXhvL2lzc3Vlcw==">GitHub</span>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><pre><code class="bash">$ hexo new "My New Post"</code></pre><p>More info: <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3Mvd3JpdGluZy5odG1s">Writing</span></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><pre><code class="bash">$ hexo server</code></pre><p>More info: <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3Mvc2VydmVyLmh0bWw=">Server</span></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><pre><code class="bash">$ hexo generate</code></pre><p>More info: <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3MvZ2VuZXJhdGluZy5odG1s">Generating</span></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><pre><code class="bash">$ hexo deploy</code></pre><p>More info: <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvL2RvY3Mvb25lLWNvbW1hbmQtZGVwbG95bWVudC5odG1s">Deployment</span></p>]]></content>
<summary type="html"><p>Welcome to <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlvLw==">Hexo</span>! This is your very first post. Check <span class="exturl"</summary>
</entry>
</feed>