Codeforces Round #327 (Div. 2)

@(K ACMer)


A. Wizards’ Duel

题意说了一大堆…就是一个简单地运算.
Alt text


B. Rebranding

题意
给你一个字符串,然后有m个操作,形如: a  b 这样的二元组,就是把字符串中为a的换为b,为b的换为a.
分析
这里字符串比较大,直接模拟相必要超时.
不过这个很明显,只需要用一个大小为26的数组,维护这个字母最终变为了什么就好了,复杂度是 O(26n) .如果再加一个大小为26的数组,作为位置标记,那么就可以在 O(n) 的复杂度完成了.


code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 20;
char a[30];
int b[30];


int main(void) {
    int n, m;
    cin >> n >> m;
    string str;
    cin >> str;
    for (int i = 0; i < 26; i++)
        a[i] = 'a' + i, b[i] = i;
    for (int i = 0; i < m; i++) {
        char x, y;
        cin >> x >> y;
        if (x == y) continue;
        a[b[x - 'a']] = y;
        a[b[y - 'a']] = x;
        swap(b[y - 'a'] , b[x - 'a']);
    }
    for (int i = 0; i < n; i++) {
        str[i] = a[str[i] - 'a'];
    }
    cout << str << endl;
    return 0;
}

C. Median Smoothing
题意
给你一个01序列a,每次遵循以下规则变换,最左边的后最右边的不变,然后新的a[i],为原来序列中 a[i1],a[i],a[i+1] 的中位数.然后这个序列变换一定次数后就会保持不变了,问你变换多少次后,序列保持不变,并输出这个序列的样子.
分析
可以观察到 1.....1 最终一定会变成 11111111
1.....0 最终一定会变成 111110000
这时候只需要求其中的孤立0或1的个数就是变换次数.比如 1110101010 其中孤立的1的个数就是三个.
这个思路下去,就只需要写一个搜索…然而有各种细节需要处理,很麻烦…最后五分钟才提交AC.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 20;
int a[5 * maxn];
int n;
int ans = 0;

void dfs(int s) {
    for (; s < n - 1; s++)
        if (a[s + 1] != a[s]) break;
    if (s == n - 1) return;
    int e, x = 0, y = 0;
    for (e = s + 1; e < n; e++) {
        if (a[e] == a[e - 1] || e == n - 1) break;
        if (a[e] == 0) x++;
        else y++;
    }
    if (a[e] == 1) ans = max(ans, x);
    else ans = max(ans, y);
    for (int i = s, j = e; i <= j; i++, j--) {
        a[i] = a[s];
        a[j] = a[e];
        if (i == j) a[i] = a[e];
    }
    dfs(e);
}

int main(void) {
    scanf("%d", &n);
    ans = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    dfs(0);
    printf("%d\n", ans);
    for (int i = 0; i < n; i++) {
        if (i) printf(" ");
        printf("%d", a[i]);
    }
    printf("\n");
    return 0;
}

D. Chip ‘n Dale Rescue Rangers(二分 + 物理)

题意
一艘船要从坐标 (a,b) 行驶到坐标 (c,d) ,最大速度为v.但是期间会刮风,风会给船x方向和y方向的分速度,前t分钟是向量为 (vx,vy) 的风,后t分钟是向量为 (wx,wy) 的风.问船所需要的最小时间到达目标点是多少?
分析
首先这样直接求这个最小时间显然是很难的,但是我们把问题转化为:已知时间t,问能否在这个时间到达目的点?这样只需二分的来假设这个时间t就可以了.
好…那么问题来了,已知时间t和最大速度v就可以得出,这艘船靠自己最多可以行驶 (vt) 的距离 maxs .
但是这样仍然不好算..各种分速度各种阶段的..
这时候….. 的威力就来了!我们可以分解为x和y来算,而且还可以把本来同时进行的动作分出一个先后顺序,我们让两股风先吹,看把船能挂到那个地方去,然后这个地方和终点的距离如果满足小于 maxs ,那么就可以在 t 的时间到达….
对于一些没法直接按照贪心策略,一步求出最优解的问题,如果解的大小满足二分的比较性质,我们就用二分答案的方法来解决
code

#include<cmath>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
double x, y, x2, y2, v, t, vx, vy, wx, wy;

bool ok(double a) {
    double sx, sy;
    if (a <= t) sx = vx * a, sy = vy * a;
    else sx = vx * t + (a - t) * wx, sy = vy * t + (a - t) * wy;
    sx = x2 - x - sx, sy = y2 - y - sy;
    if (a * v * a * v + 1e-6 >= sx * sx + sy * sy) return true;
    else return false;
}

int main(void) {
    cin >> x >> y >> x2 >> y2 >> v >> t >> vx >> vy >> wx >> wy;
    double l = 1e-9, r = 1e10;
    for (int i = 0; i < 150; i++) {
        double mid = (l + r) / 2;
        if (ok(mid)) r = mid;
        else l = mid;
    }
    cout << setprecision(16) <<  l << endl;
}

E. Three States

题意
给你一个离散的矩阵地图,图中1,2,3是三个国家的块区域,’.’是可以修建路的,’#’是不能走的.问要让这三个块相互连通,至少要在多少个点上修建道路?
Alt text

分析:
最直接的解法是从三个国家的块出发,做三个队列,实现三个方向的搜索,交替更新队列即可,但是这样实现复杂,可以分为三次,都全部搜索,再枚举三个路径的交点.
定义dp[i][x][y]为从国家i到 (x,y) 所需要的最小点数(不包括 (x,y) 这个点).
然后直接用bfs暴力更新这个dp即可.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int mod = int(1e9) + 7, INF = 0x3ffffff, maxn = 1e3 + 40;
int n, m;
char G[maxn][maxn];
bool used[maxn][maxn];
int dp[3][maxn][maxn], dirx[4] = {-1, 1, 0, 0}, diry[4] = {0, 0, -1, 1};

void bfs(char c) {
    queue<pair<int, int> > q;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (G[i][j] == c) {
                q.push(make_pair(i, j));
                dp[c - '1'][i][j] = 0;
            }
    while (!q.empty()) {
        pair<int, int> t = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int x = t.first + dirx[i], y = t.second + diry[i];
            if (x < 1 || y < 1 || x > n || y > m || G[x][y] == '#') continue;
            if (dp[c - '1'][x][y] > dp[c - '1'][t.first][t.second] + (G[t.first][t.second] == '.')) {
                dp[c - '1'][x][y] = dp[c - '1'][t.first][t.second] + (G[t.first][t.second] == '.');
                q.push(make_pair(x, y));
            }
        }
    }
}

int main(void) {
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> G[i][j];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j <= n; j++)
            for (int k = 0; k <= m; k++)
                dp[i][j][k] = INF;
    for (int i = 0; i < 3; i++) bfs(i + '1');
    int ans = INF;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            ans = min(ans, dp[0][i][j] + dp[1][i][j] + dp[2][i][j] + (G[i][j] == '.'));
    cout << (ans == INF ? -1 : ans) << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值