A:连续字母
#include <iostream> #include <string.h> #include <algorithm> using namespace std; const int N = 110; int n; char str[N]; int main() { cin >> n; while(n --) { scanf("%s", str + 1); int cnt = 0, MAX = 0; int len = strlen(str + 1); cnt ++;//第一个字符一定算一个 for(int i = 2; i<=len; i++) { if(str[i] == str[i - 1]){ cnt ++; MAX = max(cnt, MAX); } else{ cnt = 1; //从不同字符处重新开始计,肯定也包括它 } } cout << MAX << endl; } return 0; } /* 3 AAAABBCDHHH ISDHFSHFDAASDIAHSD EEEEEEE 输出: 4 2 7 */View Code
B:疯狂的快递哥
考察:单源最短路径
Dijkstra解决:
#include <iostream> #include <cstring> using namespace std; const int N = 110, M = 10010, INF = 0x3f3f3f3f; int n, m;//点,边 int g[N][N], dist[N]; bool st[N]; int pre[N]; //存储前驱结点 int dijkstra() { memset(dist, 0x3f, sizeof dist); dist[1] = 0; for(int i = 0; i<n; i++) { int t = -1; for(int j = 1; j<=n; j++) { if(!st[j] && (t == -1 || dist[t] > dist[j])) t = j; } st[t] = true; for(int j = 1; j<=n; j++) { if(dist[j] >= dist[t] + g[t][j]) pre[j] = t; dist[j] = min(dist[j], dist[t] + g[t][j]); } } if(dist[n] == INF) return INF; else return dist[n]; } void dfs(int u) { if(u == 1) { cout << u << " "; return; } dfs(pre[u]); cout << u << " "; } int main() { memset(g, 0x3f, sizeof g); cin >> n >> m; while(m --) { int a, b, c; cin >> a >> b >> c; g[a][b] = g[b][a] = min(g[a][b], c); } //初始化前驱数组 for(int i = 1; i<=n; i++) pre[i] = i; int ans = dijkstra(); dfs(n); return 0; } /* 5 6 1 2 1 2 3 5 3 4 5 3 5 10 1 3 2 4 5 4 输出:1 3 4 5 pre[n]:1 1 1 3 4 */View Code
C:subrange_sum
与2019华为OD机试题类似,但华为是要求正整数,用滑动窗口解决,这里却有负数,似乎只能暴力解
华为OD版:
考察:滑动窗口
#include <iostream> using namespace std; const int N = 1000010; int a[N]; int c, x; int main() { cin >> c >> x; for(int i = 0; i<c; i++) cin >> a[i]; int l = 0, r = 0; long long count = 0; int sum = 0; while(r < c) { //从左边开始加 sum += a[r]; while(sum >= x) { //只要sum大于x就符合要求,算作一个区间 if(sum >= x) { //当前sum已经大于x了,往后越大的数更成立 count += c - r; } sum -= a[l]; //保证区间是连续的,不会断开 l ++; } //当前sum不大于x时,r继续右移扩大区间 r ++; } cout << count << endl; return 0; }View Code
本题暴力版:
#include <iostream> using namespace std; const int N = 1000010; int a[N]; int c, x; int main() { cin >> c >> x; int cnt = 0, sum = 0; for(int i = 0; i<c; i++) { cin >> a[i]; if(a[i] >= x) //每个数自身就是一个区间 cnt ++; } for(int i = 0; i<c - 1; i++) { for(int j = i + 1; j<c; j++) { sum += a[i] + a[j]; if(sum >= x) cnt ++; } sum = 0; } cout << cnt << endl; return 0; }View Code
D:进制转换
#include <iostream> using namespace std; long long x; void Convert(int x, int n) { if(n < 16) { if(x == 0) return; else { Convert(x / n, n); cout << x % n; } } else { if(x == 0) return; else { Convert(x / n, n); int re = x % n; if(re > 9) { char ch = re - 10 + 'A'; cout << ch; } else cout << re; } } } int main() { cin >> x; Convert(x, 2); cout << endl; Convert(x, 8); cout << endl; Convert(x, 16); return 0; }View Code
E:疯狂的修路哥
考察:最小生成树
本题是用坐标形式给出的,可以先转换为点的编号,再用模板解决
#include <iostream> #include <math.h> #include <cstring> #include <algorithm> using namespace std; const int N = 10010; const double INF = 1.0 / 0.0; int n; struct Point{ int x, y, idx; }points[N]; double g[N][N]; double dist[N] = {INF}; bool st[N]; double prim() { for(int i = 1; i<=n; i++) dist[i] = INF; dist[1] = 0; double res = 0; for(int i = 0; i<n; i++) { int t = -1; for(int j = 1; j<=n; j++) { if(!st[j] && (t == -1 || dist[t] > dist[j])) t = j; } st[t] = true; if(i && dist[t] == INF) return INF; if(i) res += dist[t]; for(int j = 1; j<=n; j++) dist[j] = min(dist[j], g[t][j]); } return res; } int main() { cin >> n; //初始化 浮点型不能用memset! for(int i = 1; i<=n; i++) for(int j = 1; j<=n; j++) g[i][j] = INF; for(int i = 1; i<=n; i++) { double x, y; cin >> x >> y; points[i].x = x, points[i].y = y; points[i].idx = i; //每个点的编号 } //计算距离 for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { double dx = points[i].x - points[j].x; double dy = points[i].y - points[j].y; double c = sqrt(dx * dx + dy * dy); int a, b; //将坐标转换为编号表示 a = points[i].idx, b = points[j].idx; cout << "a = " << a << " b = " << b << " c = " << c << endl; g[a][b] = g[b][a] = min(g[a][b], c); cout << "a = " << a << " b = " << b << " g[a][b] = " << g[a][b] << endl; } } double res = prim(); if(res == INF) cout << "impossible" << endl; else printf("%.2lf", res); return 0; } /* 4 0 0 100 0 0 1 1 100 输出:200.01 */View Code
F:最长回文子序列
考察:动态规划
#include <iostream> #include <algorithm> #include <string> #include <string.h> using namespace std; const int N = 310; char str[N]; int dp[N][N]; int main() { cin >> str + 1; int len = strlen(str + 1); //统一转为小写字母 for(int i = 1; i<=len; i++) if(str[i] >= 'A' && str[i] <= 'Z' ) str[i] += 32; //A与a相差32 //初始化dp状态数组 //dp[i][j]:str[i ~ j]的最长回文子序列长度 for(int i = 1; i<=len; i++) dp[i][i] = 1; /* i <= j str[i] == str[j]时:dp[i][j] = dp[i+1][j-1] + 2,掐头去尾 str[i] != str[j]时:dp[i][j] = max(dp[i+1][j], dp[i][j-1]); 计算dp[i][j]时要计算dp[i + 1][],即i处要用到i+1的数据,所以i要从大到小 同理,j处要用到j-1的数据,故j要从小到大 */ for(int i = len; i>=0; i--) { for(int j = i + 1; j<=len; j++) { if(str[i] == str[j]) dp[i][j] = dp[i + 1][j - 1] + 2; else dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]); } } cout << dp[1][len] << endl; return 0; } /* ABCdca 输出:5 */View Code
标签:std,dist,真题,int,sum,机试,2017,include,const From: https://www.cnblogs.com/GeekDragon/p/18085941