zoukankan      html  css  js  c++  java
  • Codeforces Round #363 Div.2[111110]

    好久没做手生了,不然前四道都是能A的,当然,正常发挥也是菜。

    A:Launch of Collider

      题意:20万个点排在一条直线上,其坐标均为偶数。从某一时刻开始向左或向右运动,速度为每秒1个单位长度。输入给出每个点的坐标及其移动的方向,求发生第一次碰撞的时间,若不会碰撞,则输出-1

      最先发生碰撞的是一定是初始时相邻的两个点,因此只需对每个点循环一边,判断其是否会与下一个点碰撞,并求出其时间即可。

    #include<stdio.h>
    #include<stdlib.h>
    int N;
    int pos[200100];
    char ch[200100];
    char st[200100];
    int main()
    {
        scanf ( "%d", &N );
        getchar();
        for ( int i = 1; i <= N; i++ ) scanf ( "%c", &ch[i] );
        for ( int i = 1; i <= N; i++ ) scanf ( "%d", &pos[i] );
        int ans = 0x7FFFFFFF, p = 0;
        for ( int i = 1; i <= N; i++ )
        {
            if ( ch[i] == 'R' )
            {
                p = i;
                continue;
            }
            if ( p == 0 ) continue;
            if ( ( pos[i] - pos[p] ) / 2 < ans ) ans = ( pos[i] - pos[p] ) / 2;
        }
        if ( ans == 0x7FFFFFFF ) printf ( "-1
    " );
        else printf ( "%d
    ", ans );
        return 0;
    }
    View Code

    B:One Bomb

      题意:1000*1000的矩阵,‘.’表示空地,‘*’表示围墙。可以在任意位置按一颗炸弹,摧毁位于同一行和同一列的所有墙。问对于给定的地图,能否只用一颗炸弹炸掉所有墙。

      首先随意指定一个墙点,将其坐标与其他所有墙点比较,如果其他墙点与这个点要么在同一行,要么在同一列,则可以完成,否则能找到一个与第一个点既不在同一行也不在同一列的墙点。根据这两个点可以确定两个位置,炸弹如果要摧毁所有的墙,只能在这两个点中选择一个,分别尝试并确认即可。

    #include<stdio.h>
    int p[1001000][2];
    char str[1005][1005];
    int main()
    {
        int N, M;
        scanf ( "%d%d", &N, &M );
        for ( int i = 1; i <= N; i++ ) scanf ( "%s", &str[i][1] );
        int T = 0;
        for ( int i = 1; i <= N; i++ )
            for ( int j = 1; j <= M; j++ )
                if ( str[i][j] == '*' )
                {
                    p[++T][0] = i;
                    p[T][1] = j;
                }
        if ( T == 0 )
        {
            printf ( "YES
    1 1
    " );
            return 0;
        }
        bool find = false;
        int x, y;
        for ( int i = 2; i <= T; i++ )
            if ( p[i][0] != p[1][0] && p[i][1] != p[1][1] )
            {
                find = true;
                x = p[i][0];
                y = p[i][1];
                break;
            }
        if ( !find )
        {
            printf ( "YES
    " );
            printf ( "%d %d
    ", p[1][0], p[1][1] );
            return 0;
        }
        else
        {
            bool planA = true, planB = true;
            int x1 = x, y1 = p[1][1];
            for ( int i = 1; i <= T; i++ )
                if ( p[i][0] != x1 && p[i][1] != y1 )
                {
                    planA = false;
                    break;
                }
            int x2 = p[1][0], y2 = y;
            for ( int i = 1; i <= T; i++ )
                if ( p[i][0] != x2 && p[i][1] != y2 )
                {
                    planB = false;
                    break;
                }
            if ( !planA && !planB )
            {
                printf ( "NO
    " );
                return 0;
            }
            printf ( "YES
    " );
            printf ( "%d %d
    ", planA ? x1 : x2, planA ? y1 : y2 );
        }
        return 0;
    }
    View Code

    C:Vacations

      题意:每天可以有3种选择,发呆,锻炼身体或者打比赛,连着两天如果不发呆则做的事不能相同。求发呆的最少天数。

      f[i][0]表示到第i天位置且当天发呆的最小发呆天数,f[i][1]表示当天锻炼身体,f[i][2]表示当天打比赛。

    #include<stdio.h>
    int MIN2 ( int a, int b )
    {
        return a < b ? a : b;
    }
    int MIN3 ( int a, int b, int c )
    {
        int t = 10000;
        if ( t > a ) t = a;
        if ( t > b ) t = b;
        if ( t > c ) t = c;
        return t;
    }
    int f[200][5];
    int d[200];
    int main()
    {
        int N;
        scanf ( "%d", &N );
        for ( int i = 1; i <= N; i++ ) scanf ( "%d", &d[i] );
        f[0][0] = 0;
        f[0][1] = 1000;
        f[0][2] = 1000;
        for ( int i = 1; i <= N; i++ )
        {
            if ( d[i] == 0 )
            {
                f[i][0] = MIN3 ( f[i - 1][0], f[i - 1][1], f[i - 1][2] ) + 1;
                f[i][1] = 1000;
                f[i][2] = 1000;
            }
            if ( d[i] == 1 )
            {
                f[i][0] = MIN3 ( f[i - 1][0], f[i - 1][1], f[i - 1][2] ) + 1;
                f[i][1] = MIN2 ( f[i - 1][0], f[i - 1][2] );
                f[i][2] = 1000;
            }
            if ( d[i] == 2 )
            {
                f[i][0] = MIN3 ( f[i - 1][0], f[i - 1][1], f[i - 1][2] ) + 1;
                f[i][1] = 1000;
                f[i][2] = MIN2 ( f[i - 1][0], f[i - 1][1] );
            }
            if ( d[i] == 3 )
            {
                f[i][0] = MIN3 ( f[i - 1][0], f[i - 1][1], f[i - 1][2] ) + 1;
                f[i][1] = MIN2 ( f[i - 1][0], f[i - 1][2] );
                f[i][2] = MIN2 ( f[i - 1][0], f[i - 1][1] );
            }
        }
        printf ( "%d
    ", MIN3 ( f[N][0], f[N][1], f[N][2] ) );
        return 0;
    }
    /*
           8
           1 1 1 1 1 1 1 2
    0 0    1 1 2 2 3 3 4 4
    1 x    0 1 1 2 2 3 3 x
    2 x    x x x x x x x 3
    1->0,1
    2->0,2
    3->0,1,2
    */
    View Code

    D:Fix a Tree

      题意:给定n个点各自的父亲,得到一个n个点n条边的有向图。每次可以修改一个点的父亲,求最少修改多少次才能得到一棵树(树的根节点的父亲是其自身)。

      首先在给出的点里找到一个父亲是自身的点作为根节点,然后从图中搜索环,并把环上任意一点的父亲改为根节点。若找不到父亲为自身的点,则任意找到图中的一个环,从环上断开,并将断点的父亲修改为自身,作为根节点,并重复之前的步骤。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    int fa[210000];
    bool v[210000], u[210000];
    int main()
    {
        int N, Root = -1, cnt;
        scanf ( "%d", &N );
        for ( int i = 1; i <= N; i++ ) scanf ( "%d", &fa[i] );
        memset ( v, false, sizeof ( v ) );
        for ( int i = 1; i <= N; i++ )
            if ( fa[i] == i )
            {
                Root = i;
                v[i] = true;
                break;
            }
        if ( Root != -1 )
        {
            cnt = 0;
            for ( int i = 1; i <= N; i++ )
                if ( !v[i] )
                {
                    memset ( u, false, sizeof ( u ) );
                    int x = i;
                    v[x] = true;
                    u[x] = true;
                    while ( !v[fa[x]] )
                    {
                        v[fa[x]] = true;
                        u[fa[x]] = true;
                        x = fa[x];
                    }
                    if ( u[fa[x]] )
                    {
                        cnt++;
                        fa[x] = Root;
                    }
                }
        }
        else
        {
            Root = 1;
            v[1] = true;
            while ( !v[fa[Root]] )
            {
                v[fa[Root]] = true;
                Root = fa[Root];
            }
            cnt = 1;
            fa[Root] = Root;
            for ( int i = 1; i <= N; i++ )
                if ( !v[i] )
                {
                    memset ( u, false, sizeof ( u ) );
                    int x = i;
                    v[x] = true;
                    u[x] = true;
                    while ( !v[fa[x]] )
                    {
                        v[fa[x]] = true;
                        u[fa[x]] = true;
                        x = fa[x];
                    }
                    if ( u[fa[x]] )
                    {
                        cnt++;
                        fa[x] = Root;
                    }
                }
        }
        printf ( "%d
    ", cnt );
        for ( int i = 1; i < N; i++ ) printf ( "%d ", fa[i] );
        printf ( "%d
    ", fa[N] );
        return 0;
    }
    View Code

    E:LRU

      题意:自己读吧,懒得写了。

      题目里问1e100次后的概率,显然不用真的算到1e100,它只是表示一个“足够多”的概念。由于每种目标或者有或者没有只有两种状态,而目标的数目最多20个,因此可以用一个20位的二进制数表示所有可能的状态。经过足够多的次数后,槽位全部被填满,此后的状态转移并不影响概率。因此对于每一种状态,只需计算刚刚好达到这种状态的概率即可,也就是说,不用考虑弹出之前的某个目标的情况。

    #include<stdio.h>
    int N, K;
    double p[22];
    double ans[22];
    double dp[1 << 20 + 100];
    int main()
    {
        int k;
        double sp;
        scanf ( "%d%d", &N, &K );
        for ( int i = 0; i < N; i++ )
        {
            scanf ( "%lf", &p[i] );
        }
        dp[0] = 1;
        for ( int i = 1; i < ( 1 << N ); i++ )
        {
            sp = 0;
            k = 0;
            for ( int j = 0; j < N; j++ )
            {
                if ( ( ( 1 << j ) &i ) == 0 )
                {
                    sp += p[j];
                    k++;
                }
            }
            if ( N - k > K ) continue;
            for ( int j = 0; j < N; j++ )
            {
                if ( p[j] < 0.000000001 ) continue;
                if ( ( ( 1 << j ) &i ) != 0 )
                {
                    dp[i] += dp[i - ( 1 << j )] * p[j] / ( sp + p[j] );
                    ans[j] += dp[i - ( 1 << j )] * p[j] / ( sp + p[j] );
                }
            }
        }
        for ( int i = 0; i < N; i++ )
        {
            printf ( "%.10lf ", ans[i] );
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Unity The Method Signature Matching Rule
    Unity The Property Matching Rule
    Unity The Type Matching Rule
    Unity The Custom Attribute Matching Rule
    Unity The Member Name Matching Rule
    Unity No Policies
    Unity The Return Type Matching Rule
    Unity The Parameter Type Matching Rule
    Unity The Namespace Matching Rule
    关于TSQL递归查询的(转)
  • 原文地址:https://www.cnblogs.com/dramstadt/p/5738355.html
Copyright © 2011-2022 走看看