程设2023期末
A.围栏
#include <iostream> using namespace std; int main(){ long long n, ans = 0;cin>>n; for(long long i = 1; i <= n; ++i){ if (n % i) break; long long tmp = n % i; if (tmp < i) break; ans = max(ans, (i + tmp) * 2); }cout<<ans<<endl; return 0; }
B.解密
#include <iostream> #include <cstdio> using namespace std; string solve(string a){ int len = a.length(); int mid = (len + 1) / 2; if (len <= 2) return a; string str1(a, 1, mid - 1), str2(a, mid, len - mid), str3(a, 0, 1); return solve(str1) + str3 + solve(str2); } int main(){ string a;cin>>a; cout<<solve(a)<<endl; return 0; }
String语法
直接把string作为参数在函数中传递,看似浪费时间,实际上复杂度也是
C.传送法术
#include <iostream> #include <cstdio> using namespace std; const int inf = 1000000000; int n;string a; int f[2000]; int main(){ cin>>n>>a;int s, t; for (int i = 0; i < n; ++i){ f[i] = inf; if (a[i] == 'S') s = i; if (a[i] == 'T') t = i; }f[s] = 0; for (int j = 0; j < n; ++j){ for(int i = 0; i < n; ++i){ if (a[i] == '#') continue; if (i != 0) f[i] = min(f[i], f[i - 1] + 1); if (i != n) f[i] = min(f[i], f[i + 1] + 1); f[i] = min(f[i], f[n - i - 1] + 1); } } if(f[t] == inf) cout<<-1; else cout<<f[t]; return 0; }
用floyd的思想,最多进行n次松弛操作,复杂度
D.购买优惠券
二分答案,不知道为什么边界总是调不好
#include <iostream> #include <cstdio> #define int long long using namespace std; int a[200000]; int n, m, sum = 0; bool solve(int x){ int cnt = 0, now = 0; for (int i = 1; i <= n; ++i){ if (a[i] > x) return false; if (now + a[i] > x) {cnt++; now = 0;} now += a[i]; if (cnt > m) return false; } if (cnt == m && now > 0) return false; return true; } signed main(){ cin>>n>>m; for (int i = 1; i <= n; ++i) { cin>>a[i];sum += a[i]; } int l = (n + m - 1) / m, r = sum + 1; while (l < r){ int mid = (l + r) / 2; if (solve(mid)) r = mid; else l = mid + 1; } cout<<l<<endl; return 0; }
E.建筑修建
经典贪心
#include<iostream> #include<algorithm> using namespace std; int n, m, x[2000], y[2000]; struct building{ int l,r; }a[2000]; bool cmp(building x, building y) {return x.r < y.r;} int main() { cin>>n>>m; for (int i = 1; i <= n; ++i){ cin>>x[i]>>y[i]; a[i].l = x[i]; a[i].r = x[i] + y[i] - 1; } sort(a + 1, a + n + 1, cmp); int now = -1, ans = 0; for (int i = 1; i <= n; ++i){ if (a[i].l > now && a[i].r < m){ ++ans;now = a[i].r; } } cout<<ans<<endl; return 0; }
F.预测赢家
#include <iostream> #include <vector> using namespace std; vector<int> a; int solve(int l, int r){ if (r == l) return a[l]; if (r - l == 1) return max(a[l], a[r]) - min(a[l], a[r]); return max(min(solve(l + 2, r) + a[l] - a[l + 1], solve(l + 1, r - 1) + a[l] - a[r]), min(solve(l, r - 2) + a[r] - a[r - 1], solve(l + 1, r - 1) + a[r] - a[l])); } int main(){ int T;cin>>T;while (T--){ int m;cin>>m;a.clear(); for (int i = 1; i <= m; ++i) { int x;cin>>x;a.push_back(x); } if (solve(0, m - 1) >= 0) cout<<"true"<<endl; else cout<<"false"<<endl; } return 0; }
读题!!!又吃了没读懂题就开始写代码的亏,think twice code once
G.海拔
最小生成树(并查集)。
#include <iostream> #include <map> #include <algorithm> using namespace std; int n, m, h[500][500]; struct edge{ pair<int, int> s, t; int len; bool operator < (const edge& temp)const{ return len < temp.len; } }a[200000];int cnt; map<pair<int, int>, pair<int, int> > fa; void add(int sx, int sy, int tx, int ty, int len){ a[++cnt].len = len; a[cnt].s = make_pair(sx, sy); a[cnt].t = make_pair(tx, ty); fa[a[cnt].s] = a[cnt].s;fa[a[cnt].t] = a[cnt].t; } auto fnd(auto x){ if (fa[x] == x) return x; else return fa[x] = fnd(fa[x]); } int main(){ cin>>n>>m; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j){ cin>>h[i][j]; if (i > 1) add(i, j, i - 1, j, abs(h[i][j] - h[i - 1][j])); if (j > 1) add(i, j, i, j - 1, abs(h[i][j] - h[i][j - 1])); } sort(a + 1, a + cnt + 1); pair<int, int> S = make_pair(1, 1), T = make_pair(n, m); for (int i = 1; i <= cnt; ++i){ auto s = a[i].s, t = a[i].t; if (fnd(s) != fnd(t)) fa[fnd(s)] = fnd(t); if (fnd(S) == fnd(T)) {cout<<a[i].len<<endl;return 0;} } return 0; }
I.取数游戏
爆搜
#include <iostream> #include <vector> using namespace std; struct lecture{ int k, v; vector<int> c; }a[200]; int n, ans; int vis[20]; bool f(int now){ for (int i = 0; i < a[now].c.size(); ++i){ if (vis[a[now].c[i]]) return 0; }return 1; } void dfs(int now, int nowv){ if (now > n) return; if (f(now)){ for (int i = 0; i < a[now].c.size(); ++i){ vis[a[now].c[i]] = 1; } ans = max(ans, nowv + a[now].v); dfs(now + 1, nowv + a[now].v); for (int i = 0; i < a[now].c.size(); ++i){ vis[a[now].c[i]] = 0; } } dfs(now + 1, nowv); } int main(){ cin>>n; for (int i = 1; i <= n; ++i){ cin>>a[i].k>>a[i].v; for (int j = 0; j < a[i].k; ++j){ int x;cin>>x;a[i].c.push_back(x); } } dfs(1, 0); cout<<ans<<endl; return 0; }
H.课程安排
仍然是爆搜
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n, m, a[10][10], ans; int vis[10][10]; int fx[9] = {0, 0, 0, 1, 1, 1, -1, -1, -1}; int fy[9] = {0, 1, -1, 0, 1, -1, 0, 1, -1}; bool f(int x, int y){ for(int i = 0; i < 9; ++i) if(vis[x + fx[i]][y + fy[i]]) return 0; return 1; } void dfs(int x, int y, int now){ if (x == n && y == m) return; if (f(x, y)){ vis[x][y] = 1; ans = max(ans, now + a[x][y]); dfs(y == m ? x + 1 : x, y == m ? 1 : y + 1, now + a[x][y]); vis[x][y] = 0; } dfs(y == m ? x + 1 : x, y == m ? 1 : y + 1, now); } int main(){ int T;cin>>T;while (T--){ cin>>n>>m; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) cin>>a[i][j]; dfs(1, 1, 0); cout<<ans<<endl; ans = 0; } }
J.分配工作
搜索剪枝,这种分组类型的搜索还不熟练。
剪枝应该是叫IDA*的思想(?),就是剪掉大于阈值的部分
#include <iostream> #include <cstdio> using namespace std; const int inf = 1000000000; int ans = inf, cnt; int t[20], vis[20]; void dfs(int n, int k, int now, int nowmax){ if (n == 0 && k == 0){ ans = min(ans, nowmax); return; } for (int i = 1; i < cnt; ++i){ if (vis[i]) continue; vis[i] = 1; if (now + t[i] > nowmax && k != 0){ dfs(n - 1, k - 1, t[i], max(nowmax, t[i])); } if (n - 1 >= k && now + t[i] < ans){ dfs(n - 1, k, now + t[i], max(nowmax, now + t[i])); } vis[i] = 0; } } int main(){ int k;cin>>cnt>>k; for (int i = 0; i < cnt; ++i) cin>>t[i]; dfs(cnt - 1, k - 1, t[0], t[0]); cout<<ans<<endl; return 0; }
K.蛇入迷宫
#include <iostream> #include <vector> using namespace std; int n, a[200][200], vis[200][200], ans = 1000000000; void dfs(int x, int y, int to, int now){ if(x == n - 1 && y == n - 1 && to == 1){ ans = min(ans, now);return; } vis[x][y] = 1; if (to == 1){ if (y + 1 < n && a[x][y + 1] == 0 && vis[x][y + 1] == 0){ dfs(x, y + 1, 1, now + 1); } if (x + 1 < n && a[x + 1][y] == 0 && a[x + 1][y - 1] == 0 && vis[x + 1][y - 1] == 0){ dfs(x + 1, y, 1, now + 1); dfs(x + 1, y - 1, 0, now + 1); } } else{ if (x + 1 < n && a[x + 1][y] == 0 && vis[x + 1][y] == 0){ dfs(x + 1, y, 0, now + 1); } if (y + 1 < n && a[x][y + 1] == 0 && a[x - 1][y + 1] == 0 && vis[x - 1][y + 1] == 0){ dfs(x, y + 1, 0, now + 1); dfs(x - 1, y + 1, 1, now + 1); } } vis[x][y] = 0; } int main(){ cin>>n; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) cin>>a[i][j]; if (a[n - 1][n - 1] || a[n - 1][n - 2]) {cout<<-1<<endl;return 0;} dfs(0, 1, 1, 0);//pos of head is (0, 1), its body is level if (ans != 1000000000) cout<<ans<<endl; else cout<<-1<<endl; return 0; }
L.最长奇异子序列
因为我们更新状态的时候只会考虑上一个数而不会考虑之前的数,所以设 f[i][j] 表示前i个数形成的最长奇异子序列且最后一个数的第 j 位是 1 。那么 f[i][j] = max{f[i - 1][k]} + a[i][j], k 是 a[i] 为 1 的数位。
滚动数组优化到一维。(lyt实在太强了
#include <iostream> #include <cstdio> using namespace std; int a[200000], f[100000]; int g(int x){ int ret = 0; for (int j = 1; j <= 32; ++j){ if (x % 2) ret = max(ret, f[j]); }return ret + 1; } int main(){ int T;cin>>T;while (T--){ int n, ans = 0;cin>>n; for (int i = 1; i <= n; ++i){ cin>>a[i]; int num = g(a[i]); for (int j = 1; j <= 32; ++j){ if (a[i] % 2) f[j] = num; a[i] /= 2; ans = max(ans, f[j]); } } cout<<ans<<endl; }return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效