CF #301 div2

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 | 1

using 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 | 1

using 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 | 1

using 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 | 1

using 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值