2021PTA天梯赛

L1-1

#include 
using namespace std;

int main(int argc, char const *argv[]) {
	puts("To iterate is human, to recurse divine.");
}

L1-2

#include 
using namespace std;
int a, b, c;

int main(int argc, char const *argv[]) {
	cin >> a >> b >> c;
	cout << a - b * c << endl;
}

L1-3

#include 
using namespace std;

int main(int argc, char const *argv[]) {
	string s; cin >> s;
	if (s.length() == 4) {
		if ((s[0] - '0') * 10 + (s[1] - '0') < 22) cout << 20 << s[0] << s[1] << '-' << s[2] << s[3] << endl;
		else cout << 19 << s[0] << s[1] << '-' << s[2] << s[3] << endl;
	}
	else cout << s[0] << s[1] << s[2] << s[3] << "-" << s[4] << s[5] << endl;
}

L1-4

#include 
using namespace std;
int n, m; double p;

int main(int argc, char const *argv[]) {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> p;
		if (p < m)
			cout << "On Sale! " << fixed << setprecision(1) << p << endl;
	}
}

L1-5

#include 
using namespace std;
int s[25];

int main(int argc, char const *argv[]) {
	for (int i = 1; i <= 24; i++) cin >> s[i];
	int n;
	while (cin >> n) {
		if (n < 0 or n > 23) break;
		n++;
		if (s[n] > 50) cout << s[n] << " Yes\n";
		else cout << s[n] << " No\n";
	}
}

L1-6

由于下面的输入是getline(),所以输入字符串之前要用一个getchar()把回车吃掉。

#include 
using namespace std;
int n, m; string s, f;

int main(int argc, char const *argv[]) {
	cin >> n >> m;
	getchar();
	for (int i = 1; i <= n; i++) {
		getline(cin, s);
		if (f.size()) continue;
		if (~s.find("qiandao") or ~s.find("easy")) continue;
		if (m == 0) {
			f = s;
			continue;
		}
		m--;
	}
	if (f.size()) cout << f << endl;
	else puts("Wo AK le");
}

L1-7

#include 
using namespace std;
map<int, int> m;
int n;

int main(int argc, char const *argv[]) {
	cin >> n;
	int x, maxx = 0, minn = 1e7;
	for (int i = 1; i <= n; i++) {
		cin >> x;
		maxx = max(maxx, x);
		minn = min(minn, x);
		m[x]++;
	}
	cout << minn << " " << m[minn] << endl << maxx << " " << m[maxx] << endl;
}

L1-8

这个题第一遍做完发现样例没过,这才知道理解错了题,不管数列多长,都是从第一个数开始一个一个慢慢往后乘,而不是乘新出现的两个数,应该模拟好样例再开始写的。

#include 
#define A 1010

using namespace std;
int a3, n, a[A];

int main(int argc, char const *argv[]) {
	cin >> a[1] >> a[2] >> n;
	int len = 2, now = 1;
	while (len <= n) {
		a3 = a[now] * a[now + 1];
		if (a3 > 9) {
			if (len + 2 <= n) {
				a[++len] = a3 / 10;
				a[++len] = a3 % 10;
			}
			else if (len + 1 <= n) {
				a[++len] = a3 / 10;
				break;
			}
			else break;
		}
		else a[++len] = a3;
		now++;
	}
	for (int i = 1; i <= n; i++) cout << a[i] << " \n"[i == n];
}

L2-1

#include 
#define A 100010

using namespace std;
int n, m, S, cnt, x, point[A], ans_cnt;
string s[A];
char sta[A], ans[A]; int top;

int main(int argc, char const *argv[]) {
	cin >> n >> m >> S;
	for (int i = 1; i <= n; i++) {
		cin >> s[i];
		point[i] = 1;
		s[i] = " " + s[i];
	}
	while (cin >> x) {
		if (x == -1) break;
		if (x == 0) {
			if (top == 0) continue;
			ans[++ans_cnt] = sta[top];
			top--;
		}
		else if (point[x] + 1 <= (int)s[x].length()) {
			if (top + 1 > S) {
				ans[++ans_cnt] = sta[top];
				top--;
			}
			sta[++top] = s[x][point[x]];
			point[x]++;
		}
	}
	for (int i = 1; i <= ans_cnt; i++) cout << ans[i];
}

L2-2

d f s dfs dfs或者 b f s bfs bfs都可以,由于题目要求输出字典序最小的最长链,所以在输入之后接着把能到达的点排一下序。

#include 
#define A 100010

using namespace std;
int n, k, x, s, in[A], fa[A], maxx, ans, out[A], cnt;
vector<int> v[A];
void bfs(int s) {
	queue<pair<int, int> > q;
	q.push(make_pair(s, 1));
	while (!q.empty()) {
		int fr = q.front().first, frcnt = q.front().second; q.pop();
		if (frcnt > maxx) {
			maxx = frcnt;
			ans = fr;
		}
		for (auto i : v[fr]) q.push(make_pair(i, frcnt + 1));
	}
}

int main(int argc, char const *argv[]) {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> k;
		for (int j = 0; j < k; j++) {
			cin >> x;
			in[x]++;
			fa[x] = i;
			v[i].push_back(x);
		}
	}
	for (int i = 0; i < n; i++) {
		sort(v[i].begin(), v[i].end());
		if (in[i] == 0) s = i;
	}
	bfs(s);
	cout << maxx << endl;
	while (ans != s) {
		out[++cnt] = ans;
		ans = fa[ans];
	}
	out[++cnt] = s;
	for (int i = cnt; i >= 1; i--) cout << out[i] << " \n"[i == 1];
}

L2-3

#include 
#define A 10010

using namespace std;
struct node {
	vector<int> v;
	int cnt;
	friend bool operator < (const node a, const node b) {
		if (a.cnt != b.cnt) return a.cnt > b.cnt;
		else return a.v < b.v;
	}
}nv[A];
map<vector<int>, int> cnt, vis;
vector<int> v[A];

int main(int argc, char const *argv[]) {
	int n, m, num = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			int x; scanf("%d", &x);
			v[i].push_back(x);
		}
		cnt[v[i]]++;
	}
	for (int i = 1; i <= n; i++) {
		if (vis[v[i]]) continue;
		vis[v[i]] = 1;
		nv[++num] = node{v[i], cnt[v[i]]};
	}
	sort(nv + 1, nv + num + 1);
	cout << num << endl;
	for (int i = 1; i <= num; i++) {
		cout << nv[i].cnt << " ";
		for (int j = 0; j < (int)nv[i].v.size(); j++)
			cout << nv[i].v[j] << " \n"[j == (int)nv[i].v.size() - 1];
	}
}

L2-4

#include 
#define A 100010

using namespace std;
int n, m, a[A];
vector<int> v[A];

int main(int argc, char const *argv[]) {
	cin >> n >> m;
	for (int i = 1, k; i <= n; i++) {
		cin >> k;
		v[i].push_back(k);
		for (int j = 1, x; j <= k; j++) {
			cin >> x;
			v[i].push_back(x);
		}
	}
	int now = 1, opt, j;
	while (m--) {
		cin >> opt >> j;
		if (opt == 0) {
			now = v[now][j];
		}
		else if (opt == 1) {
			cout << now << endl;
			a[j] = now;
		}
		else if (opt == 2) {
			now = a[j];
		}
	}
	cout << now << endl;
}

L3-1

先是想到了一个 Θ ( n q ) \Theta{(nq)} Θ(nq)的做法:预处理出起点到所有点的使用现金的最小花费 w 1 [ ] w1[] w1[]、所有点到终点的使用旅游金的最小花费 w 2 [ ] w2[] w2[],前者建正图求,后者建反图求,然后枚举把现金兑换成旅游金的点,若当前枚举到点 i i i,点 i i i的兑换汇率为 a [ i ] a[i] a[i],即在点 i i i处把现金全部兑换成旅游金,则整趟旅途的花费为 w 1 [ i ] + w 2 [ i ] / a [ i ] + ( w 2 [ i ] % a [ i ] ! = 0 ) w1[i]+w2[i]/a[i]+(w2[i]\%a[i]!=0) w1[i]+w2[i]/a[i]+(w2[i]%a[i]!=0)(前半段用现金,后半段用旅游金,整除则不需要加一),每次更改之后都重新枚举一边点,求出最小花费,可以拿到 21 21 21分。
由于每次只是更改一个点的汇率,所以其实不需要每次重新枚举一遍所有点,只需要考虑更改的这个点是否产生更优解,即每次更改汇率之前将这个点的原本解删除,更改汇率之后重新计算解并算入最优值。这里不能只用 s e t set set存一个值,因为可能有多个点的路径是同一个值,所以需要用一个第二维来区分一下。
再就是注意点不可达的情况,不用更新。

#include 
#define A 200010

using namespace std;
typedef long long ll;
struct node {
	int next, to; ll c, d;
}e[A], e2[A];
int head[A], num;
void add(int fr, int to, ll c, ll d) {
	e[++num].next = head[fr];
	e[num].to = to;
	e[num].c = c;
	e[num].d = d;
	head[fr] = num;
}
int n, m, q; ll a[A];
struct STA {
	ll w; int id;
	STA() {w = LLONG_MAX;}
	bool operator < (const STA &a) const {
		return w > a.w;
	}
}sta[A];
bool vis[A];
void dijkstra(int s) {
	for (int i = 1; i <= n; i++) sta[i].id = i;
	priority_queue<STA> q;
	sta[s].w = 0; q.push(sta[s]);
	while (!q.empty()) {
		int fr = q.top().id; q.pop(); vis[fr] = 1;
		for (int i = head[fr]; i; i = e[i].next) {
			int ca = e[i].to;
			if (sta[ca].w > sta[fr].w + e[i].c) {
				sta[ca].w = sta[fr].w + e[i].c;
				q.push(sta[ca]);
			}
		}
	}
}
int head2[A], num2;
void add2(int fr, int to, ll c, ll d) {
	e2[++num2].next = head2[fr];
	e2[num2].to = to;
	e2[num2].c = c;
	e2[num2].d = d;
	head2[fr] = num2;
}
struct STA2 {
	ll w; int id;
	STA2() {w = LLONG_MAX;}
	bool operator < (const STA2 &a) const {
		return w > a.w;
	}
}sta2[A];
bool vis2[A];
void dijkstra2(int s) {
	for (int i = 1; i <= n; i++) sta2[i].id = i;
	priority_queue<STA2> q;
	sta2[s].w = 0; q.push(sta2[s]);
	while (!q.empty()) {
		int fr = q.top().id; q.pop(); vis2[fr] = 1;
		for (int i = head2[fr]; i; i = e2[i].next) {
			int ca = e2[i].to;
			if (sta2[ca].w > sta2[fr].w + e2[i].d) {
				sta2[ca].w = sta2[fr].w + e2[i].d;
				q.push(sta2[ca]);
			}
		}
	}
}

int main(int argc, char const *argv[]) {
	cin >> n >> m >> q;
	for (int i = 1; i <= m; i++) {
		int u, v; ll c, d;
		scanf("%d%d%lld%lld", &u, &v, &c, &d);
		if (u == v) continue;
		add(u, v, c, d);
		add2(v, u, c, d);
	}
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	dijkstra(1);
	dijkstra2(n);
	int x; ll y;
	set<pair<ll, int> > s;
	for (int i = 1; i <= n; i++) {
		if (sta[i].w == LLONG_MAX or sta2[i].w == LLONG_MAX) continue;
		s.insert(make_pair(sta[i].w + sta2[i].w / a[i] + (sta2[i].w % a[i] != 0), i));
	}
	while (q--) {
		scanf("%d%lld", &x, &y);
		if (sta[x].w == LLONG_MAX or sta2[x].w == LLONG_MAX) {
			cout << s.begin()->first << endl;
			continue;
		}
		auto tmp = s.find(make_pair(sta[x].w + sta2[x].w / a[x] + (sta2[x].w % a[x] != 0), x));
		s.erase(tmp);
		a[x] = y;
		s.insert(make_pair(sta[x].w + sta2[x].w / a[x] + (sta2[x].w % a[x] != 0), x));
		cout << s.begin()->first << endl;
	}
}

L3-2

这个题目纸条的数量是 100 100 100,用纸条去对高度 d f s dfs dfs就可以过。

#include 
#define A 100010

using namespace std;
int n, m, height[A];
bool vis[101], fl;
vector<int> h[101], f;
void dfs(int fr) {
	if ((int)f.size() == m) {
		fl = 1;
		for (int i = 0; i < (int)f.size(); i++) cout << f[i] << " \n"[i == (int)f.size() - 1];
		return;
	}
	if (fl) return;
	for (int i = 1; i <= m; i++) {
		if (vis[i]) continue;
		bool flag = 0;
		for (int j = 0; j < (int)h[i].size(); j++) {
			if (h[i][j] != height[fr + j]) {
				flag = 1;
				break;
			}
		}
		if (flag) continue;
		f.push_back(i);
		vis[i] = 1;
		dfs(fr + h[i].size() - 1);
		f.pop_back();
		vis[i] = 0;
	}
}

int main(int argc, char const *argv[]) {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> height[i];
	cin >> m;
	for (int i = 1; i <= m; i++) {
		int k; cin >> k;
		for (int j = 0; j < k; j++) {
			int x; cin >> x;
			h[i].push_back(x);
		}
	}
	dfs(1);
}

你可能感兴趣的:(算法)