ACM学习历程—Codeforces Round #354 (Div. 2)

http://codeforces.com/contest/676

allzysyz学弟和hqwhqwhq的邀请下,打了我的第三场CF。。。

毕竟在半夜。。所以本来想水到12点就去睡觉的。。。结果一下次过了三题,发现第四题是个bfs,就打到了12:30.。。。BC貌似是没有了,不知道后面还会不会有,最近就打CF为主吧。。

 

A题:

http://codeforces.com/problemset/problem/676/A

应该算是比较水吧。没有什么坑点。直接枚举最大值在最左最右侧和最小值在最左最右侧四种情况。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

int main()
{
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    int n, t, indexone, indexn;
    while (scanf("%d", &n) != EOF)
    {
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &t);
            if (t == 1) indexone = i;
            if (t == n) indexn = i;
        }
        printf("%d\n", max(max(indexone, n-1-indexone), max(indexn, n-1-indexn)));
    }
    return 0;
}
View Code

 

B题:

http://codeforces.com/problemset/problem/676/B

ccpc热身赛一题的简化版,首先我可以把所有的酒强行先倒入第一杯,然后让它一层一层往下流。暴力模拟一遍就可以了。上一层的第i杯,会流入下一层的第i杯和第i+1杯。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

double a[2][10000];

int main()
{
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    int n, t, ans;
    double tmp;
    while (scanf("%d%d", &n, &t) != EOF)
    {
        bool flag;
        ans = 0;
        a[1][1] = t;
        for (int i = 1; i <= n; ++i)
        {
            memset(a[(i+1)%2], 0, sizeof(a[(i+1)%2]));
            flag = true;
            for (int j = 1; j <= i; ++j)
            {
                if (a[i%2][j] >= 1)
                {
                    tmp = a[i%2][j]-1;
                    ans++;
                    a[(i+1)%2][j] += tmp/2.0;
                    a[(i+1)%2][j+1] += tmp/2.0;
                    flag = false;
                }
            }
            if (flag) break;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

C题:

http://codeforces.com/problemset/problem/676/C

当时比较直接的想法就先求出把前i段都变成同样字符的代价的所有前缀和suma, sumb。这样就可以求解任意区间变成同样字符的代价了。

然后枚举区间左值,二分区间右值。就可以求解了。这样的复杂度是nlogn

但是考虑到区间右值其实具有单调性。于是我可以从后往前遍历区间左值,那么区间右值要么不变,要么是上一次的位置往前移动。于是用两个指针就可以2n时间内完成了。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

const int maxN = 100005;
int n, k;
int suma[maxN], sumb[maxN];
char str[maxN];

void input()
{
    scanf("%s", str);
    suma[0] = sumb[0] = 0;
    for (int i = 0; i < n; ++i)
    {
        if (str[i] == 'a')
        {
            suma[i+1] = suma[i];
            sumb[i+1] = sumb[i]+1;
        }
        else
        {
            suma[i+1] = suma[i]+1;
            sumb[i+1] = sumb[i];
        }
    }
}

int getLen(int from)
{
    int ans, lt = from, rt = n, mid;
    while (lt+1 < rt)
    {
        mid = (lt+rt)>>1;
        if (suma[mid]-suma[from-1] > k) rt = mid;
        else lt = mid;
    }
    if (suma[rt]-suma[from-1] <= k) ans = rt-from+1;
    else ans = lt-from+1;

    lt = from; rt = n;
    while (lt+1 < rt)
    {
        mid = (lt+rt)>>1;
        if (sumb[mid]-sumb[from-1] > k) rt = mid;
        else lt = mid;
    }
    if (sumb[rt]-sumb[from-1] <= k) ans = max(ans, rt-from+1);
    else ans = max(ans, lt-from+1);
    return ans;
}

void work()
{
    int ans = 0;
    for (int i = 1; i <= n; ++i)
        ans = max(ans, getLen(i));
    printf("%d\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    while (scanf("%d%d", &n, &k) != EOF)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

D题:

http://codeforces.com/problemset/problem/676/D

这题是个bfs,比较容易看出来。首先我设置一个二进制状态1111,四位,最高位表示上方有门,第二位表示右方有门,第一位表示下方有门,最低位第0位表示左方有门。

然后写个swtich,把map中所有的字符映射到二进制状态。

然后就是bfs了。

bfs带有三个状态x,y,statexy即坐标,state表示经过了几次旋转。

然后就是瞎几把搜了。。。

第一种情况(state+1)%4

第二种情况便是上下左右搜,代码我是直接复制粘贴,所以只看往上的情况。

首先这种状态下必须上方有门,而且上面的格子下方有门。

对于上方有门,由于是顺时针旋转,也就是mp的映射二进制位最高位在逆时针旋转后是1。而这个逆时针旋转就是(3+state)%4这一位了。代码里可以看出来。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

//up right down left
int get(char ch)
{
    switch (ch)
    {
        case '+': return 15;
        case '-': return 5;
        case '|': return 10;
        case '^': return 8;
        case '>': return 4;
        case '<': return 1;
        case 'v': return 2;
        case 'L': return 14;
        case 'R': return 11;
        case 'U': return 7;
        case 'D': return 13;
        case '*': return 0;
    }
}

bool judge(int p, int index)
{
    for (int i = 0; i < index; ++i)
        p >>= 1;
    return p&1;
}

const int maxN = 1005;
int n, m, fromx, fromy, tox, toy;
char mp[maxN][maxN];
int s[maxN][maxN][5];

void input()
{
    memset(mp, '*', sizeof(mp));
    memset(s, -1, sizeof(s));
    for (int i = 1; i <= n; ++i)
    {
        scanf("%s", mp[i]+1);
        mp[i][m+1] = '*';
    }
    scanf("%d%d", &fromx, &fromy);
    scanf("%d%d", &tox, &toy);
}

struct node
{
    int x, y;
    int state;
};

int myMin(int x, int y)
{
    if (x == -1) return y;
    if (y == -1) return x;
    return min(x, y);
}

void work()
{
    node t, k;
    queue<node> q;
    t.x = fromx; t.y = fromy; t.state = 0;
    s[t.x][t.y][t.state] = 0;
    q.push(t);
    while (!q.empty())
    {
        t = q.front();
        q.pop();

        k = t;
        k.state = (k.state+1)%4;
        if (s[k.x][k.y][k.state] == -1)
        {
            s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1;
            q.push(k);
        }

        int dir1, dir2;
        dir1 = get(mp[t.x][t.y]);

        //up
        if (judge(dir1, ((3+t.state)%4+4)%4))
        {
            dir2 = get(mp[t.x-1][t.y]);
            if (judge(dir2, ((1+t.state)%4+4)%4))
            {
                k.x = t.x-1;
                k.y = t.y;
                k.state = t.state;
                if (s[k.x][k.y][k.state] == -1)
                {
                    s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1;
                    q.push(k);
                }
            }
        }

        //right
        if (judge(dir1, ((2+t.state)%4+4)%4))
        {
            dir2 = get(mp[t.x][t.y+1]);
            if (judge(dir2, ((0+t.state)%4+4)%4))
            {
                k.x = t.x;
                k.y = t.y+1;
                k.state = t.state;
                if (s[k.x][k.y][k.state] == -1)
                {
                    s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1;
                    q.push(k);
                }
            }
        }

        //down
        if (judge(dir1, ((1+t.state)%4+4)%4))
        {
            dir2 = get(mp[t.x+1][t.y]);
            if (judge(dir2, ((3+t.state)%4+4)%4))
            {
                k.x = t.x+1;
                k.y = t.y;
                k.state = t.state;
                if (s[k.x][k.y][k.state] == -1)
                {
                    s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1;
                    q.push(k);
                }
            }
        }

        //left
        if (judge(dir1, ((0+t.state)%4+4)%4))
        {
            dir2 = get(mp[t.x][t.y-1]);
            if (judge(dir2, ((2+t.state)%4+4)%4))
            {
                k.x = t.x;
                k.y = t.y-1;
                k.state = t.state;
                if (s[k.x][k.y][k.state] == -1)
                {
                    s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1;
                    q.push(k);
                }
            }
        }
    }
    int ans = -1;
    ans = myMin(ans, s[tox][toy][0]);
    ans = myMin(ans, s[tox][toy][1]);
    ans = myMin(ans, s[tox][toy][2]);
    ans = myMin(ans, s[tox][toy][3]);
    printf("%d\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    while (scanf("%d%d", &n, &m) != EOF)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

posted on 2016-05-26 13:25  AndyQsmart  阅读(264)  评论(0编辑  收藏  举报

导航