题目大意:
将字符串还原成全排列。
思路:
注意到数据范围排列总数(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;
}
题目大意:
将一群人移动到出口外,每人每次仅能移动一格且不能重叠,问该过程的最短时间。
思路:
这题跟之前在百度之星比赛上做的一道题很相似。
硬模拟的话情况比较复杂不好考虑,所以我们考虑逆向思维。
我们假设所有人都已经在出口,现在需要把所有人移动到各自的位置上,这样做的目的是可以简化考虑每个人重叠的情况。
一个最优的策略是按每个人到各自位置上的距离进行排序,考虑每个人的等待时间逐渐增加,在模拟的过程中更新所需时间的最大值。
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;
}