2020牛客国庆集训派对day4部分题解

J. Jokewithpermutation

题目大意:

将字符串还原成全排列。

思路:

注意到数据范围排列总数\(n\)不超过\(50\),考虑直接暴力\(dfs\)

注意记录数字的\(vis\)数组需要开的大小,如果排列总数\(n\)恰为\(50\),意味着将会有\(9+2×41=91\)位数字,有可能在选取的过程中超过\(n=50\)的范围,所以数组需要开到\(100\)以上。

Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 104;

string s; 
bool vis[N];
vector<int> tmp, ans;
int n;
bool getAns;

void dfs(int x) {
	bool ok = 1;
	for (int i = 1; i <= n; i++) {
		if (!vis[i]) ok = 0;
	}
	if (ok) {
		for (auto i : tmp) {
			ans.push_back(i);
		}
		getAns = 1;
		return;
	}
	for (int len = 1; len <= 2; len++) {
		if (x + len - 1 <= s.length()) {
			string t = s.substr(x, len);
			if (!vis[atoi(t.c_str())]) {
				vis[atoi(t.c_str())] = 1;
				tmp.push_back(atoi(t.c_str()));
				dfs(x + len);
				if (getAns) break;
				vis[atoi(t.c_str())] = 0;
				tmp.pop_back();
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> s; 
	if (s.length() < 9) {
		n = s.length();
	} else {
		n = 9 + (s.length() - 9) / 2;
	}
	s = " " + s;
	dfs(1);
	for (auto i : ans) cout << i << " ";
	return 0;
}

C. Emergency Evacuation

题目大意:

将一群人移动到出口外,每人每次仅能移动一格且不能重叠,问该过程的最短时间。

思路:

这题跟之前在百度之星比赛上做的一道题很相似。

硬模拟的话情况比较复杂不好考虑,所以我们考虑逆向思维。

我们假设所有人都已经在出口,现在需要把所有人移动到各自的位置上,这样做的目的是可以简化考虑每个人重叠的情况。

一个最优的策略是按每个人到各自位置上的距离进行排序,考虑每个人的等待时间逐渐增加,在模拟的过程中更新所需时间的最大值。

Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;

struct Human
{
	int r, c, d;
	bool operator<(const Human& t) const { return d > t.d; }
} h[N];

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int r, s, p; cin >> r >> s >> p;
	for (int i = 1; i <= p; i++) {
		cin >> h[i].r >> h[i].c;
		if (h[i].c > s) h[i].d = h[i].c - s + r - h[i].r + 1;
		else h[i].d = s - h[i].c + 1 + r - h[i].r + 1;
	}
	sort(h + 1, h + 1 + p);
	int wait = 1;
	int ans = h[1].d;
	for (int i = 2; i <= p; i++) {
		if (h[i].d + wait > ans) ans = h[i].d + wait;
		wait++;
	}
	cout << ans << endl;
	return 0;
}
posted @ 2020-10-05 00:05  Nepenthe8  阅读(129)  评论(0编辑  收藏  举报