小红小紫投硬币
思路:签到题,直接猜 0.5 0.5 0.5
void solve() {
int n; cin >> n;
cout << 0.50000000 << '\n';
}
小红的字符串
思路:就看看左右两端变成左边的字符还是右边的字符花费的代价更小就用哪边
void solve() {
string s; cin >> s;
int l = 0, r = s.size() - 1;
int ans = 0;
while (l < r) {
char o1 = s[l], o2 = s[r];
if (o1 > o2) {
swap(o1, o2);
}
int c1 = o2 - o1;
int c2 = 'z' - o2 + o1 - 'a' + 1;
ans += min(c1, c2);
}
cout << ans << '\n';
}
小红的 01 消除
思路:就是用 1 1 1去抵消 0 0 0
void solve() {
int n; cin >> n;
string s; cin >> s;
int x, y, z; cin >> x >> y >> z;
int c0 = 0;
bool ok = false;
int ans = 0;
for (auto c : s) {
if (!y) break;
if (c == '0') c0++;
else if (c0) ans++, c0--, y --;
}
cout << ans << '\n';
}
小红组比赛
思路:一眼 d p dp dp, d p [ i ] [ j ] dp[i][j] dp[i][j]表示选前 i i i场比赛的某一个题所能得到 j j j的分数, d p [ i ] [ j ] = 0 dp[i][j] = 0 dp[i][j]=0表示不行, d p [ i ] [ j ] = 1 dp[i][j] = 1 dp[i][j]=1 表示行,最后所有可能的分数和目标值的差值更新答案就行
void solve() {
int n, m; cin >> n >> m;
vector<vector<int>> t(n + 1);
int ans = INF;
for (int i = 1; i <= n; i ++) {
for (int j = 1, x; j <= m; j ++) {
cin >> x;
t[i].push_back(x);
}
}
vector<vector<int>> dp(n + 1, vector<int>(5010));
dp[0][0] = 1;
int target; cin >> target;
for (int i = 1; i <= n; i ++) {
for (auto j : t[i]) {
for (int k = j; k <= 5010; k ++) {
dp[i][k] |= dp[i - 1][k - j];
}
}
}
for (int i = 0; i < 5010; i ++) {
if (dp[n][i]) ans = min(ans, abs(target - i));
}
cout << ans << '\n';
}
折半丢弃
思路:二分 m e x mex mex,因为 m e x mex mex越小越容易满足,越大可能不容易满足,具有二分性,先把 a [ i ] a[i] a[i]通过除 2 2 2可以变为那些数存下来, v e [ i ] ve[i] ve[i]表示哪些数可以通过除 2 2 2变为 i i i,然后二分每次 c h e c k check check的时候从 m i d mid mid往前判断是否可以,因为 m e x mex mex越大满足的数越少, m e x mex mex越小可能的数越多
void solve() {
int n; cin >> n;
vector<int> a(n + 1);
map<int, int> mp;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
mp[a[i]] ++;
}
vector<vector<int>> ve(n + 1);
for (int i = 1; i <= n; i ++) {
int x = a[i];
while (x) {
if (x >= n) {
x >>= 1;
continue;
}
ve[x].push_back(a[i]);
x >>= 1;
}
ve[0].push_back(a[i]);
}
auto check = [&](int x) -> bool {
auto vis = mp;
for (int i = x; i >= 0; i --) {
bool ok = false;
for (auto j : ve[i]) {
if (vis[j]) {
vis[j] --;
ok = true;
break;
}
}
if (!ok) return false;
}
return true;
};
int l = 0, r = n, ans = -1;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1, ans = mid;
else r = mid - 1;
}
cout << ans + 1 << '\n';
}
小红走矩阵
思路:其实感觉这个很像分层图,并且我们想一下,他只有可能不走左边或上边,所以就只有三种情况,正常走,不走左边,不走上边,可以写三个 b f s bfs bfs来处理,我为了方便直接在一个 b f s bfs bfs函数里面进行, v i s [ i ] [ j ] [ k ] [ l ] vis[i][j][k][l] vis[i][j][k][l]表示 i i i和 j j j这个位置不能往 k k k这种类型的方向走 l l l为 0 0 0表示不能穿墙, 1 1 1表示可以,然后就是队列里面维护位置,不能走那个方向,能否穿墙,距离起点的距离
int n, m, ans;
char g[N][N];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int vis[N][N][5][2];
int bfs() {
queue<array<int, 5>> q;
q.push({1, 1, 2, 1, 0});
q.push({1, 1, 3, 1, 0});
q.push({1, 1, 4, 0, 0});
vis[1][1][2][1] = 1;
vis[1][1][3][1] = 1;
vis[1][1][4][0] = 1;
while (q.size()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++) {
if (i == t[2]) continue;
int tx = t[0] + dx[i];
int ty = t[1] + dy[i];
if (tx < 1 || ty < 1 || tx > n || ty > m) continue;
if (vis[tx][ty][t[2]][t[3]]) continue;
if (tx == n && ty == m) return t[4] + 1;
if (g[tx][ty] == 'X') {
if (t[3]) {
vis[tx][ty][t[2]][t[3]] = 1;
q.push({tx, ty, t[2], 0, t[4] + 1});
}
} else {
vis[tx][ty][t[2]][t[3]] = 1;
q.push({tx, ty, t[2], t[3], t[4] + 1});
}
}
}
return -1;
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
cin >> g[i][j];
}
}
ans = bfs();
cout << ans << '\n';
}
游游的删点直径
思路:待补