#include <iostream> #include <algorithm> using namespace std; int GetNum(int a[], int begin, int end) { int num = 0; for (int i = begin; i < end; ++i) num = num * 10 + a[i]; return num; } int main() { int n, len = 0, a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cin >> n; int Temp = n, ans = 0; while (Temp) { Temp /= 10; len++; } do { int num = 0; for (int i = 0; i < len; ++i) { num = num * 10 + a[i]; if(num >= n) break; int k = n, j = 9 - (i + 1); k -= num; int mid = (j >> 1) + 1; while (mid < 9) { int num1 = GetNum(a, i + 1, mid); int num2 = GetNum(a, mid, 9); if (0 == num1 % num2 && k == num1 / num2) ans++; mid++; } } } while (next_permutation(a, a + 9)); cout << ans; return 0; }第二题:剪格子
#include <iostream> using namespace std; const int maxn = 12; int n, m, a[maxn][maxn], vis[maxn][maxn], sum, ans; int dir[4][2] = { {0, 1},{0,-1},{1,0},{-1,0} }; void dfs(int x, int y, int cnt, int blank) { if (cnt * 2 >= sum) { if (blank > ans && cnt * 2 == sum) ans = blank; return; } for (int i = 0; i < 4; ++i) { int dx = x + dir[i][0], dy = y + dir[i][1]; if (dx >= 0 && dx < n && dy >= 0 && dy < m) { if (!vis[dx][dy]) { vis[dx][dy] = 1; dfs(dx, dy, cnt + a[dx][dy], blank + 1); vis[dx][dy] = 0; } } } } int main() { cin >> m >> n; for(int i = 0;i < n;++i) for (int j = 0; j < m; ++j) { cin >> a[i][j]; sum += a[i][j]; } if (sum & 1) cout << 0; else { dfs(0, 0, a[0][0], 1); cout << ans; } return 0; }第三题:大臣的旅费
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <vector> #include <cstring> using namespace std; const int maxn = 10005; struct Edge { int dest, cost; Edge(int d, int c) :dest(d), cost(c) { } }; vector<Edge> G[maxn]; int n, ans, cnt, vis[maxn]; int dfs(int p, int Len) { if (vis[p]) return cnt; if (cnt < Len) cnt = Len; vis[p] = 1; for (int i = 0; i < (int)G[p].size(); ++i) if (!vis[G[p][i].dest]) dfs(G[p][i].dest, Len + G[p][i].cost); return cnt; } int main() { scanf("%d", &n); for (int i = 1; i < n; ++i) { int a, b, c; scanf("%d %d %d", &a, &b, &c); G[a].push_back(Edge(b, c)); G[b].push_back(Edge(a, c)); } for (int i = 1; i <= n; ++i) { int Temp = dfs(i, 0); if (ans < Temp) ans = Temp; cnt = 0; memset(vis, 0, sizeof(vis)); } printf("%d", ans * 10 + (ans + 1) * ans / 2); return 0; }
这题是求树的直径,那咱们干脆来说一讲这个算法:树的直径前端
由于树是一种比较特殊的数据结构,树上的任意两个点均可以互联通,而且联通方式惟一!由于树是一个最大无环图,最小联通图!那么既然任意两个点均可互联通了,就确定有两个点之间的距离是全部的两个点组成的点对的距离中最大的!求这个最大值就是求树的直径!
怎样?树的直径是否是就是很符合这个题目的特征啊?ios
随便从一个点出发可以到达的最远的点,必定是树的直径的一个端点!
为何呢?这个能够反证:假设选取任意点 p
由于树的直径的端点到 p 点也是有路径的,假设端点为A和B,若是从 p 出发可以到达的最远的点不是A也不是B,而是C,那么从A(或者B)出发,可以到达的最远的点也就不是B(或者A)了!这个你们能够在纸上画一下,就可发现!算法
第一次dfs:找到距离出发点p最远的点A,它是直径的一个端点
第二次dfs:从直径的端点出发,找到最远的点,这个距离就是直径!markdown
这样就从一开始的n次dfs到2次dfs,就能经过了!数据结构
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <vector> #include <cstring> using namespace std; const int maxn = 10005; struct Edge { int dest, cost; Edge(int d, int c) :dest(d), cost(c) { } }; vector<Edge> G[maxn]; int n, ans = -1, MaxPoint = -1, vis[maxn]; void dfs(int p, int Len) { if (vis[p]) return ; if (ans < Len) { ans = Len; MaxPoint = p; } vis[p] = 1; for (int i = 0; i < (int)G[p].size(); ++i) if (!vis[G[p][i].dest]) dfs(G[p][i].dest, Len + G[p][i].cost); return ; } int main() { scanf("%d", &n); for (int i = 1; i < n; ++i) { int a, b, c; scanf("%d %d %d", &a, &b, &c); G[a].push_back(Edge(b, c)); G[b].push_back(Edge(a, c)); } dfs(1, 0); ans = -1; memset(vis, 0, sizeof(vis)); dfs(MaxPoint, 0); printf("%d", ans * 10 + (ans + 1) * ans / 2); return 0; }
说实话,前端时间大部分精力都放在了密码学的研究和编码方面去了,其次就是搞面向对象的程序设计练习去了,已经有好一阵子没作算法训练了(惭愧!)因为即将到来蓝桥杯、还有csp、天梯赛、西安邀请赛之类的,这些都会在疫情结束以后陆续举办,仍是得加紧训练啊!这几个题都是不算难的搜索训练题,那个树的直径比较有意思,值得关注!ide