Codeforces Round #327 (Div. 2)

来源:互联网 发布:51单片机寄存器有哪些 编辑:程序博客网 时间:2024/05/21 23:00

@(K ACMer)

        • A Wizards Duel
        • B Rebranding
        • D Chip n Dale Rescue Rangers二分 物理
        • E Three States


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