ABC301 复盘

ABC301 复盘

At 链接

LG 链接

[ABC301A] Overall Winner

思路解析:从头开始遍历字符串,遇到一个字符就给对应的一方加分,输出第一个胜场大于 \(\lceil n / 2\rceil\) 的一方。

#include<bits/stdc++.h>
using namespace std;
int n;
string str;
int main() {
	cin >> n;
	cin >> str;
	int win = (int)ceil((double)n / 2);
	int a = 0, t = 0;
	for(int i = 0; i < n; i++) {
		if(str[i] == 'A') a++;
		else if(str[i] == 'T') t++;
		if(a >= win) {
			cout << "A";
			return 0;
		}
		else if(t >= win) {
			cout << "T";
			return 0;
		}
	}
	return 0;
}

[ABC301B] Fill the Gaps

思路解析:对于每两个相邻的数直接顺序输出它们之间的数即可

#include<bits/stdc++.h>
using namespace std;
int n;
int a[110];
int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for(int i = 1; i < n; i++) {
		cout << a[i] << " ";
		if(a[i] - a[i + 1] > 1) {
			for(int j = a[i] - 1; j > a[i + 1]; j--) {
				cout << j << " ";
			}
		}
		else if(a[i] - a[i + 1] < -1) {
			for(int j = a[i] + 1; j < a[i + 1]; j++) {
				cout << j << " ";
			}
		}
	}
	cout << a[n];
	return 0;
}

[ABC301C] AtCoder Cards

思路解析:先分别用一个 map 记录下两个字符串每个字母的出现次数,然后对于每一个出现次数不同的字母,判断是否是 atcoder 中的任意一个,如果是,则判断剩下的 @ 符够不够用。

#include<bits/stdc++.h>
using namespace std;
string s, t;
map<char, int> mps, mpt;
set<char> st;
set<char> atcoder;
bool check(char ch) {
	return atcoder.find(ch) != atcoder.end();
}
void init() {
	atcoder.insert('a');
	atcoder.insert('t');
	atcoder.insert('c');
	atcoder.insert('o');
	atcoder.insert('d');
	atcoder.insert('e');
	atcoder.insert('r');
}
int main() {
	init();
	cin >> s >> t;
	for(int i = 0; i < s.size(); i++) {
		mps[s[i]]++;
	}
	for(int i = 0; i < t.size(); i++) {
		mpt[t[i]]++;
	}
	for(int i = 0; i < t.size(); i++) {
		if(mpt[t[i]] != mps[t[i]]) {
			st.insert(t[i]);
		}
		if(mpt[s[i]] != mps[s[i]]) {
			st.insert(s[i]);
		}
	}
	st.erase('@');
	for(auto it : st) {
		if(!check(it)) {
			cout << "No";
			return 0;
		}
		if(mpt[it] > mps[it]) {
			mps['@'] -= mpt[it] - mps[it];
			if(mps['@'] < 0) {
				cout << "No";
				return 0;
			}
		}
		if(mpt[it] < mps[it]) {
			mpt['@'] -= mps[it] - mpt[it];
			if(mpt['@'] < 0) {
				cout << "No";
				return 0;
			}
		}
	}
	cout << "Yes";
	return 0;
}

[ABC301D] Bitmask

思路解析:贪心 + 纯模拟,先把不是 ? 的值算出来,然后遍历每一个 ?,如果加上 ? 后的值 小于等于 \(n\) 就把答案加上 ? 对应位的值。

错因:切记这里的二进制是反向输入的,每一位的值是 \(2 ^ \left(n - i + 1 \right)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n;
string str;
int main() {
	cin >> str;
	ll x;
	cin >> x;
	n = x;
	ll sum = 0;
	for(int i = 0; i < str.size(); i++) {
		if(str[i] == '1') {
			sum += (ll)1 << (str.size() - i - 1);	//切记反向求
		}
	}
	if(sum > n) {
		cout << "-1";
		return 0;
	}
	for(int i = 0; i < str.size(); i++) {
		if(str[i] == '?') {
			ll temp = ((ll)1 << (str.size() - i - 1));
			if(sum + temp <= n) {
				sum += temp;
			}
		}
	}
	cout << sum;
	return 0;
}

[ABC301E] Pac-Takahashi

思路解析:注意到猴子数小于等于18,可以想到状压dp,加上起点和终点总共20个点正好符合状压dp的要求。先用 \(n\) 次 dfs 求出每两个猴子之间或到终点和起点的距离,若起点到终点的距离就 大于 \(t\) 那就直接输出 -1 然后返回,之后就做常规状压dp,最后对于每一种状态判断时间是否足够,若足够就统计抓到的猴子数求 \(max\)

__builtin_popcount(i) 可以用来求 i 的二进制中 1 的个数

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define fir first
#define sec second
int n, m, t;
char ch[310][310];
int sx, sy, gx, gy;
int d[310][310];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
vector< PII > v;
int dis[30][30];
int sv, gv;
int f[2000010][30];
bool check(int x, int y) {
	return x > 0 && x <= n && y > 0 && y <= m;
}
void bfs(int xx, int yy) {
	queue< PII > q;
	q.push({xx, yy});
	memset(d, 0x3f, sizeof(d));
	d[xx][yy] = 0;
	while(!q.empty()) {
		int x = q.front().fir, y = q.front().sec;
		q.pop();
		for(int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if(check(nx, ny) && ch[nx][ny] != '#' && d[nx][ny] > d[x][y] + 1) {
				d[nx][ny] = d[x][y] + 1;
				q.push({nx, ny});
			}
		}
	}
}
int main() {
	cin >> n >> m >> t;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			cin >> ch[i][j];
			if(ch[i][j] == 'S') {
				sx = i;
				sy = j;
				v.push_back({i, j});
				sv = v.size() - 1;
			}
			else if(ch[i][j] == 'G') {
				gx = i;
				gy = j;
				v.push_back({i, j});
				gv = v.size() - 1;
			}
			else if(ch[i][j] == 'o') {
				v.push_back({i, j});
			}
		}
	}
	swap(v[sv], v[0]);
	sv = 0;
	swap(v[gv], v[v.size() - 1]);
	gv = v.size() - 1;
	for(int i = 0; i < v.size(); i++) {
		int xx = v[i].fir, yy = v[i].sec;
		bfs(xx, yy);
		for(int j = 0; j < v.size(); j++) {
			dis[i][j] = d[v[j].fir][v[j].sec];
		}
	}
//	cout << sv << " " << gv << " " << dis[sv][gv] << "\n";
	if(dis[sv][gv] > t) {
		cout << "-1";
		return 0;
	}
	memset(f, 0x3f, sizeof(f));
	f[1][0] = 0;
	for(int i = 1; i < (1 << v.size()); i++) {
		if(i & 1) {
			for(int j = 0; j < v.size(); j++) {
				if((i >> j) & 1) {
					for(int k = 0; k < v.size(); k++) {
						if((i >> k) & 1) {
							f[i][j] = min(f[i][j], f[i ^ (1 << j)][k] + dis[k][j]);
						}
					}
				}
			}
		}
	}
	int ans = 0;
	for(int i = 1; i < (1 << v.size()); i++) {
		if((i & 1) && ((i >> (v.size() - 1)) & 1)) {
			if(f[i][v.size() - 1] <= t) {
				ans = max(ans, __builtin_popcount(i) - 2);
			}
		}
	}
	cout << ans;
	return 0;
}
posted @ 2023-12-10 16:12  2020luke  阅读(59)  评论(0)    收藏  举报