CF #301 div2

来源:互联网 发布:做编程用什么电脑配置 编辑:程序博客网 时间:2024/05/01 16:06

A:

题意:

给两个串t,p,像密码锁那样每次滑动一个,问最短滑动多少次。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 1000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);char p[maxn];char t[maxn];int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int n;    scanf("%d", &n);    scanf("%s%s", p, t);    int ans = 0;    for (int i = 0; i < n; i++)    {        int pp = p[i] - '0';        int tt = t[i] - '0';        ans += min(abs(pp - tt), 10 - abs(pp - tt));    }    cout << ans << endl;    return 0;}

B:

题意:

天才小明有n门考试,已经考了k门,每一门的考试分数范围是1~p,他太厉害了可以控制自己考试分数考在范围内的任意分数上。

小明为了不让自己太装逼,所以他想让自己的分数的和小于等于x,但是为了让他妈继续给他打游戏,他成绩的中位数又不能低于y。

现在给你已经考了k门的课程的成绩,让你计算余下满足要求的n - k门考试他应该考多少分。

解析:

这题数据太神了。

首先先确定,为了让分数小于等于x,中位数不低于y,考的任意分数就可以确定了,最低用1,最高用y,这样处理就可以让两个条件满足并且简化。

然后为了使中位数落在y之上,最后分数集合中大于等于y的数应该大于小于等于y的数的。

所以用余下的分数总和除以y来计算最多可以放入多少个y,然后协调左右,计算出结果。

注意的是,给的数据中,有可能可以放入的y的个数远远大于余下课程数量,所以要加个取小的数的判断。,。

并且,在确定了之后,还要调整大于y的个数和小于y的个数。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 1000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int n, k, p, x, y;    scanf("%d%d%d%d%d", &n, &k, &p, &x, &y);    int sumMark = 0;    int greaterThan = 0;    int lessThan = 0;    for (int i = 0; i < k; i++)    {        int t;        scanf("%d", &t);        sumMark += t;        if (y <= t)        {            greaterThan++;        }        else        {            lessThan++;        }    }    int remainNum = n - k;    int remainSum = x - sumMark;//    cout << remainNum << " " << remainSum << endl;//    cout << greaterThan << " " << lessThan << endl;    int cntGT = remainSum / y;    int cntLT = remainNum - cntGT;//    cout << cntGT << " " << cntLT << endl;    cntGT = min(cntGT, remainNum);    cntLT = remainNum - cntGT;    while (cntGT * y + 1 * cntLT > remainSum && cntGT != -1)    {        cntGT--;        cntLT++;    }    if (cntGT == -1)    {        printf("-1\n");    }    else    {//        cout << cntGT << " " << cntLT << endl;        if (cntGT + greaterThan < cntLT + lessThan)        {            printf("-1\n");        }        else        {//        cout << cntGT << " " << cntLT << endl;            for (int i = 0; i < cntGT; i++)            {                printf("%d ", y);            }            for (int i = 0; i < cntLT; i++)            {                printf("1 ");            }        }    }    return 0;}

C:

题意:

给一个n * m的冰面。

“ . ” 代表这个冰面还没有被踩过;“ X ”表示这个冰面已经被踩过了,再次踩这个冰面的时候就会掉下去。

现在小明从 sx,sy出发,问他能否从 ex, ey,这个点掉到冰面下去。

解析:

开始弱智了,想先找到ex,ey然后去找某条路径能回到ex,ey。

然后LGG提醒,找到ex,ey之后,若ex,ey是“X”,那就直接YES了;

如果不是,只要判断终点周围存不存在“ . ", 如果存在,肯定能回到ex,ey并且掉下去。

所以先用bfs() , O(n)找到终点,并且标记上每一点的step。

找到终点后,判断周围有”."并且未被step标记或者周围有”.",标记的step大于终点的step,或者周围有”."并且有两个相等的step,即YES,否则NO。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 500 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};int n, m;char g[maxn][maxn];int sx, sy, ex, ey;int step[maxn][maxn];struct Node{    int x, y;    Node(int _x, int _y)    {        x = _x;        y = _y;    }};bool isOk(int x, int y){    int ans[4];    int cnt = 0;    for (int i = 0; i < 4; i++)    {        int nx = x + dir[i][0];        int ny = y + dir[i][1];        if (0 <= nx && nx < n && 0 <= ny && ny < m)        {            if ((step[nx][ny] == -1 && g[nx][ny] == '.') || step[x][y] < step[nx][ny])                return true;            else if (step[nx][ny] != -1)                ans[cnt++] = step[nx][ny];        }    }//    cout << cnt << endl;    sort(ans, ans + cnt);//    for (int i = 0; i < cnt; i++)//        cout <<ans[i]<< endl;    for (int i = 1; i < cnt; i++)        if (ans[i - 1] == ans[i])            return true;    return false;}bool bfsFindWay(){    memset(step, -1, sizeof(step));    queue<Node> q;    step[sx][sy] = 0;    q.push(Node(sx, sy));    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        if (x == ex && y == ey)        {            return isOk(ex, ey);        }        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < n && 0 <= ny && ny < m)            {                if (nx == ex && ny == ey && g[nx][ny] == 'X')                    return true;                if (g[nx][ny] != 'X')                {                    if (step[nx][ny] == -1)                    {                        step[nx][ny] = step[x][y] + 1;                        q.push(Node(nx, ny));                    }                }            }        }    }    return false;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    scanf("%d%d", &n, &m);    for (int i = 0; i < n; i++)    {        scanf("%s", g[i]);    }    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);    sx--, sy--, ex--, ey--;    if (bfsFindWay())    {        printf("YES\n");    }    else    {        printf("NO\n");    }//    for (int i = 0; i < n; i++)//    {//        for (int j = 0; j < m; j++)//        {//            printf("%5d ", step[i][j]);//        }//        printf("\n");//    }    return 0;}

D:

题意:

有三种生物生活在一个海岛上,锤子,剪刀,布,他们之间锤子可以吃剪刀,剪刀吃布,布吃锤子,每种生物相遇的概率是一样的。

现在给出三种生物的初始数量,计算经过足够长的时间以后,只剩下锤子的概率R,只剩下剪刀的概率S,只剩下布的概率P。。

解析:

设当前有锤子r只,剪刀s只,布p只,则锤子吃了剪刀的概率是: r * s / (r * s + r * p + s * p)。

所以 dp[ i ] [ j ] [ k ] 表示海岛上只剩下i只锤子,j只剪刀,k只布的时候的概率。

若布吃了锤子:

 if (j != 0 || k != 0)    dp[i][j][k] += ((i + 1.0) * k / ((i + 1) * j + (i + 1) * k + j * k)) * dp[i + 1][j][k];
若锤子吃了剪刀:

if (i != 0 || k != 0)    dp[i][j][k] += ((j + 1.0) * i / (i * (j + 1) + i * k + (j + 1) * k)) * dp[i][j + 1][k];
若剪刀吃了布:

if (i != 0 || j != 0)    dp[i][j][k] += ((k + 1.0) * j / (i * j + i * (k + 1) + j * (k + 1))) * dp[i][j][k + 1];

初始状态下:

dp[ r ] [ s ] [ p ] = 1


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 100 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);double dp[maxn][maxn][maxn];int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int r, s, p;    scanf("%d%d%d", &r, &s, &p);    memset(dp, 0, sizeof(dp));    dp[r][s][p] = 1.0;    for (int i = r; i >= 0; i--)    {        for (int j = s; j >= 0; j--)        {            for (int k = p; k >= 0; k--)            {                ///all die,  all live                if ((i == 0 && j == 0 && k == 0) || (i == r && j == s && k == p))                    continue;                ///k ate a i                if (j != 0 || k != 0)                    dp[i][j][k] += ((i + 1.0) * k / ((i + 1) * j + (i + 1) * k + j * k)) * dp[i + 1][j][k];                ///i ate a j                if (i != 0 || k != 0)                    dp[i][j][k] += ((j + 1.0) * i / (i * (j + 1) + i * k + (j + 1) * k)) * dp[i][j + 1][k];                ///j ate a k                if (i != 0 || j != 0)                    dp[i][j][k] += ((k + 1.0) * j / (i * j + i * (k + 1) + j * (k + 1))) * dp[i][j][k + 1];            }        }    }    double R = 0, S = 0, P = 0;    for (int i = 1; i <= r; i++)        R += dp[i][0][0];    for (int i = 1; i <= s; i++)        S += dp[0][i][0];    for (int i = 1; i <= p; i++)        P += dp[0][0][i];    printf("%.12lf %.12lf %.12lf\n", R, S, P);    return 0;}


0 0