A-乘积最大
题意
给定一个数字字符串,把字符串分成`K+1`个数,使这些数乘积最大。
分析
本题最佳解法应该是区间dp
但本蒟蒻不会dp。只能暴力dfs了。
在串中插入*
其性质和排列类似。可以参考蓝书P15递归实现排列型枚举
。
对于在第i
个位置插入*
分成i
之前的为一段,及i和i之后一段。
需要注意在数字相连时的边界情况。
AC代码
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; const int maxn = 50; string a; int n, k; int vis[maxn]; ll s[maxn]; ll ans = -1; void dfs(int x) { if (x == k) { ll x = 1; int t = 0; memset(s, 0, sizeof(s)); s[t] = a[0] - 48; for (int i = 1; i < n; i++) { if (vis[i - 1]) { s[++t] = (a[i] - '0'); } else { s[t] = s[t] * 10 + (a[i] - '0'); } } for (int i = 0; i <= t; i++) { x *= s[i]; } ans = max(ans, x); return; } for (int i = 0; i < n - 1; i++) { if (vis[i]) continue; vis[i] = 1; dfs(x + 1); vis[i] = 0; } } int main(void) { FAST_IO; cin >> n >> k; cin >> a; dfs(0); cout << ans << endl; return 0; }
C-单词接龙
题意
给定一个字符和一些字符串,按照字符串之间重叠的部分,连接字符串,求最长的连接长度。
分析
比较经典的DFS+字符串,比较考察细节,比如字符串的模拟操作、dfs回溯的处理。
有两种基本的思路:
- 对于字符串,本题数据较少,可以搜索时暴力处理。使用C++的string比较方便,但仍需要注意边界细节。(我写的时候在substr上调了好久,emmmm)
- 比较好的做法可以先预处理一个
数组,其中
表示串i和串j之间可以连接的字符数。在DFS的时候使用
进行回溯等操作。
AC代码
方法1(string暴力)
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; int const maxn = 50; int vis[maxn]; vector<string> v_str; int ans = 0; void dfs(string &s) { int flag = 0; for (int i = 0; i < (int)v_str.size(); i++) { if (vis[i] >= 2) continue; string &ts = v_str[i]; int n = 0; int len1 = (int)s.length(); int len2 = (int)ts.length(); for (int j = 0; j < min(len1, len2); j++) { if (ts.substr(0, j + 1) == s.substr(len1 - j - 1)) { flag = 1; n = j + 1; break; } } if (n) { vis[i]++; auto temp = s; s = s + ts.substr(n); dfs(s); s = temp; vis[i]--; } } if (!flag) { ans = max((int)s.length(), ans); } } int main(void) { FAST_IO; int n; cin >> n; for (int i = 0; i < n; i++) { string s; cin >> s; v_str.push_back(s); } string s; cin >> s; dfs(s); cout << ans << endl; return 0; }
方法2(预处理字符数)
#include <bits/stdc++.h> using namespace std; int n; string dc[25]; int cd[25][25]; int cs[25]; int mincd(int x,int y) { bool p=true; int ky=0; for(int k=dc[x].size()-1;k>=0;k--) { for(int kx=k;kx<dc[x].size();kx++) if(dc[x][kx]!=dc[y][ky++]) { p=false; break; } if(p==true) return dc[x].size()-k; ky=0; p=true; } return 0; } char sta; int ans=0; int mans=0; void dfs(int p) { bool jx=false; for(int i=1;i<=n;i++) { if(cs[i]>=2) continue; if(cd[p][i]==0) continue; if(cd[p][i]==dc[p].size() || cd[p][i]==dc[i].size()) continue; mans+=dc[i].size()-cd[p][i]; cs[i]++; jx=true; dfs(i); //接上 mans-=dc[i].size()-cd[p][i]; //回溯 cs[i]--; } if(jx==false) ans=max(ans,mans); return ; } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>dc[i]; cin>>sta; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cd[i][j]=mincd(i,j); for(int i=1;i<=n;i++){ if(dc[i][0]==sta){ cs[i]++; mans=dc[i].size(); dfs(i); cs[i]=0; } } cout<<ans<<endl; return 0; }
D-Cow Line
题意
有一些人排队,允许进行以下四种操作:
- A L ----- 从左边插入一人
- A R ----- 从右边插入一人
- D L N ----- 从左边走出N人
- D R N ----- 从右边走出N人
问最后队伍中的序号。
分析
用双端队列模拟入队出队,即可。复杂度
AC代码
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; deque<int> q; int main(void) { FAST_IO; int n; cin >> n; string opt, dir; int num = 0, k; while (n--) { cin >> opt >> dir; if (opt == "A") { if (dir == "L") { q.push_front(++num); } else { q.push_back(++num); } } else { cin >> k; if (dir == "L") { for (int i = 0; i < k && !q.empty(); i++) q.pop_front(); } else { for (int i = 0; i < k && !q.empty(); i++) q.pop_back(); } } } while (!q.empty()) { cout << q.front() << endl; q.pop_front(); } return 0; }
G-Cow Digit Game
分析
好像是道SG函数的博弈裸题,队友说套一下SG函数就好了。直接上代码吧。
AC代码
#include <bits/stdc++.h> using namespace std; int g, n; bool sg[1000005]; int main() { for(int i = 1; i <= 9; i++) sg[i] = true; for(int i = 10; i <= 1000000; i++) { int ma = 0, mi = 10, t = i; while(t) { int x = t % 10; if(x) mi = min(mi, x); ma = max(ma, x); t /= 10; } if(sg[i - ma] && sg[i - mi]) sg[i] = false; else sg[i] = true; } cin >> g; for(int i = 0; i < g; i++) { cin >> n; if (sg[n]) cout << "YES" << endl; else cout << "NO" << endl; } }
I-旅行家的预算
分析
一道操作比较繁琐的贪心+模拟
。可以转换区间贪心。加入起点与终点共n+2
个站点。
若当前在点i
则需要考虑若在当前站点加多少油可以到达下一个便宜的站点。如果无法到达下一个便宜的站,那就需要加满油。
复杂度
本题的N超级小。。
AC代码
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; int const maxn = 20; struct node { double d, p; bool operator<(const node &obj) const { if (d == obj.d) return p < obj.p; return d < obj.d; } }D[maxn]; int main(void) { FAST_IO; int n; double d, c, cd, p; cin >> d >> c >> cd >> p >> n; D[0].p = p; for (int i = 1; i <= n; i++) { cin >> D[i].d >> D[i].p; } D[n + 1].d = d; D[n + 1].p = 0; sort(D + 1, D + 1 + n); double total = 0, oil = 0, x = 0; for (int i = 0; i <= n + 1; i++) { oil -= (D[i].d - x) / cd;//当前剩余的油量 if (oil < 0) { total = -1; break; } int j = i + 1; while (D[j].p > D[i].p && j <= n) {//寻找比当前要便宜的站点 j++; } double need = (D[j].d - D[i].d) / cd; need = min(c, need); double add = need - oil; if (add > 0) { total += add * D[i].p; oil += add; } x = D[i].d; } if (total == -1) { cout << "No Solution" << endl; } else { cout << fixed << setprecision(2) << total << endl; } return 0; }
K-Hide and Seek
题意
奶牛贝西和农夫约翰(FJ)玩捉迷藏,现在有N个谷仓,FJ开始在第一个谷仓,贝西为了不让FJ找到她,当然要藏在距离第一个谷仓最远的那个谷仓了。现在告诉你N个谷仓,和M个两两谷仓间的“无向边”。每两个仓谷间当然会有最短路径,现在要求距离第一个谷仓(FJ那里)最远的谷仓是哪个(所谓最远就是距离第一个谷仓最大的最短路径)?如有多个则输出编号最小的。以及求这最远距离是多少,和有几个这样的谷仓距离第一个谷仓那么远。
分析
只要求出1-N的单源最短路,遍历找出最大值就可。因为本题所有边的边权全是1,所以只要从1开始bfs遍历图就行了。复杂度O(N+M)
.
// C++的STL里有一些直接的简单算法可用(以下算法复杂度均为O(N)): //头文件 algorithm max_element(begin(), end(), cmp); //找到序列最大值,返回其指针 min_element(begin(), end(), cmp); //找到序列最小值,返回其指针 count(begin(), end(), value) //统计序列中为value值的个数
AC 代码
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; int const maxn = 50000 + 10; struct node { int v, next; }e[maxn << 1]; int head[maxn], cnt; int dis[maxn], vis[maxn]; void add(int u, int v) { e[cnt].v = v; e[cnt].next = head[u]; head[u] = cnt++; } void bfs() { queue<pair<int, int>> q; dis[1] = 0; vis[1] = 1; q.push(make_pair(1, 0)); while (!q.empty()) { auto x = q.front(); q.pop(); int u = x.first; dis[u] = x.second; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if (vis[v]) continue; vis[v] = 1; q.push(make_pair(v, x.second + 1)); } } } int main(void) { FAST_IO; memset(head, -1, sizeof(head)); int n, m; cin >> n >> m; for (int i = 0; i < m; i++) { int u, v; cin >> u >>v; add(u, v); add(v, u); } bfs(); int mx = *max_element(dis + 1, dis + 1 + n); int cont = count(dis + 1, dis + 1 + n, mx); int p = 0; for (int i = 1; i <= n; i++) { if (dis[i] == mx) { p = i; break; } } cout << p << " " << mx << " " << cont << endl; return 0; }
L-回文数
分析
模拟N进制加法,并判断回文。
AC代码
#include <bits/stdc++.h> using namespace std; #define FAST_IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) typedef long long ll; typedef unsigned int UINT; typedef unsigned long long ull; int n; string clac(string a) { string ans, b(a); reverse(b.begin(), b.end()); ans.resize(a.length()); int d = 0; for (int i = a.length() - 1; i >= 0; i--) { int x, y; if (isdigit(a[i])) { x = a[i] - '0'; } else { x = a[i] - 'A' + 10; } if (isdigit(b[i])) { y = b[i] - '0'; } else { y = b[i] - 'A' + 10; } int c = (x + y + d) % n; if (c < 10) ans[i] = c + '0'; else { ans[i] = c - 10 + 'A'; } d = (x + y + d) / n; } if (d > 0) ans.insert(ans.begin(), d < 10 ? d + '0' : d - 10 + 'A'); return ans; } bool ok(string &s) { int len = (int)s.length(); for (int i = 0; i < len / 2; i++) { if (s[i] != s[len - 1 - i]) { return false; } } return true; } int main(void) { FAST_IO; string m; cin >> n >> m; int ans = 0; while (!ok(m)) { m = clac(m); ans++; if (ans > 30) { cout << "Impossible!" << endl; break; } } if (ans <= 30) cout << "STEP=" << ans << endl; return 0; }