• noip模拟赛 蒜头君救人


    分析:之前的一道模拟赛题是dp+dfs,这道题是dp+bfs.

          我们设f[stu][i][j]为当前状态为stu,走到(i,j)的答案,考虑怎么设计stu,每个人的状态有3种:要么在原地,要么被背着,要么已经到了终点,那么用一个3进制数保存就可以了.

          下面考虑怎么转移,直接递推肯定是不对的,dfs也不行,只能bfs了.我们每次可以选择不走,或者如果当前点有人就背起来,或者到了终点就放下所有人或者放下所有使速度变慢的人,写好几次转移就过了.

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int inf = 0x7ffffff;
    
    int n, m, k, top, sx, sy, tx, ty, a[20][20], speed[30], f[60010][15][15], dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 },flag[20];
    char name[30][3],s[20][20];
    
    struct node
    {
        int x, y, zhuangtai;
    };
    
    int jisuan(int stu)
    {
        int tot = 0,sped = k;
        memset(flag, 0, sizeof(flag));
        while (stu)
        {
            tot++;
            flag[tot] = stu % 3;
            stu /= 3;
        }
        for (int i = 1; i <= top; i++)
            if (flag[i] == 1)
                sped += speed[i];
        if (sped < 1)
            sped = 1;
        return sped;
    }
    
    bool judge(int x, int y)
    {
        if (x >= 1 && x <= n && y >= 1 && y <= m)
            return true;
        return false;
    }
    
    int bei(int stu, int x, int y)
    {
        int cur, tot = 0;
        for (int i = 1; i <= top; i++)
            if (s[x][y] == name[i][0])
            {
                cur = i;
                break;
            }
        memset(flag, 0, sizeof(flag));
        while (stu)
        {
            tot++;
            flag[tot] = stu % 3;
            stu /= 3;
        }
        if (flag[cur])
            return 0;
        flag[cur] = 1;
        for (int i = top; i >= 1; i--)
            stu = stu * 3 + flag[i];
        return stu;
    }
    
    int fang1(int stu, int x, int y)
    {
        memset(flag, 0, sizeof(flag));
        int tot = 0;
        while (stu)
        {
            tot++;
            flag[tot] = stu % 3;
            stu /= 3;
        }
        for (int i = 1; i <= top; i++)
            if (flag[i] == 1)
                flag[i] = 2;
        for (int i = top; i >= 1; i--)
            stu = stu * 3 + flag[i];
        return stu;
    }
    
    int fang2(int stu, int x, int y)
    {
        int tot = 0;
        memset(flag, 0, sizeof(flag));
        while (stu)
        {
            tot++;
            flag[tot] = stu % 3;
            stu /= 3;
        }
        for (int i = 1; i <= top; i++)
            if (flag[i] == 1 && speed[i] > 0)
                flag[i] = 2;
        for (int i = top; i >= 1; i--)
            stu = stu * 3 + flag[i];
        return stu;
    }
    
    int qpow(int a, int b)
    {
        int res = 1;
        while (b)
        {
            if (b & 1)
                res *= a;
            a *= a;
            b >>= 1;
        }
        return res;
    }
    
    void bfs()
    {
        queue <node> q;
        node temp;
        temp.x = sx;
        temp.y = sy;
        temp.zhuangtai = 0;
        q.push(temp);
        while (!q.empty())
        {
            node u = q.front();
            q.pop();
            int sudu = jisuan(u.zhuangtai),x = u.x,y = u.y;
            //printf("%d %d %d
    ", sudu, x, y);
            for (int i = 0; i < 4; i++)
            {
                int nx = x + dx[i], ny = y + dy[i];
                if (judge(nx, ny))
                {
                    //只移动
                    if (s[nx][ny] != '#' && f[u.zhuangtai][nx][ny] > f[u.zhuangtai][x][y] + sudu)
                    {
                        f[u.zhuangtai][nx][ny] = f[u.zhuangtai][x][y] + sudu;
                        node temp;
                        temp.x = nx;
                        temp.y = ny;
                        temp.zhuangtai = u.zhuangtai;
                        q.push(temp);
                    }
                    //背人
                    if (s[nx][ny] >= 'A' && s[nx][ny] <= 'Z')
                    {
                        int stu = bei(u.zhuangtai, nx, ny);
                        if (f[stu][nx][ny] > f[u.zhuangtai][x][y] + sudu)
                        {
                            f[stu][nx][ny] = f[u.zhuangtai][x][y] + sudu;
                            node temp;
                            temp.zhuangtai = stu;
                            temp.x = nx;
                            temp.y = ny;
                            q.push(temp);
                        }
                    }
                    //放人
                    if (s[nx][ny] == 't')
                    {
                        int stu1 = fang1(u.zhuangtai, nx, ny);
                        int stu2 = fang2(u.zhuangtai, nx, ny);
                        if (f[stu1][nx][ny] > f[u.zhuangtai][x][y] + sudu)
                        {
                            f[stu1][nx][ny] = f[u.zhuangtai][x][y] + sudu;
                            node temp;
                            temp.zhuangtai = stu1;
                            temp.x = nx;
                            temp.y = ny;
                            q.push(temp);
                        }
                        if (f[stu2][nx][ny] > f[u.zhuangtai][x][y] + sudu)
                        {
                            f[stu2][nx][ny] = f[u.zhuangtai][x][y] + sudu;
                            node temp;
                            temp.zhuangtai = stu2;
                            temp.x = nx;
                            temp.y = ny;
                            q.push(temp);
                        }
                    }
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++)
        {
            scanf("%s", s[i] + 1);
            for (int j = 1; j <= m; j++)
            {
                if (s[i][j] == 's')
                {
                    sx = i;
                    sy = j;
                }
                else
                {
                    if (s[i][j] == 't')
                    {
                        tx = i;
                        ty = j;
                    }
                    else
                    {
                        if (s[i][j] >= 'A' && s[i][j] <= 'Z')
                            top++;
                    }
                }
            }
        }
        for (int i = 1; i <= top; i++)
            scanf("%s%d", name[i], &speed[i]);
        for (int i = 0; i <= 60000; i++)
            for (int j = 1; j <= 10; j++)
                for (int l = 1; l <= 10; l++)
                    f[i][j][l] = inf;
        f[0][sx][sy] = 0;
        bfs(); 
        printf("%d
    ", f[qpow(3, top) - 1][tx][ty]);
    
        return 0;
    }
  • 相关阅读:
    软件工程 2+ 自动生成四则运算题 测试版
    面向对象 (5)计算柱体体积可换底
    面向对象 (4)正方形的周长和面积
    软件工程 3.关于软件质量保障初探
    面向对象 (3)四棱柱的体积与数的判断
    面向对象 (1)矩形的面积和周长
    面向对象 (2)n的阶乘与两点距离
    软件工程 2.20194650 自动生成四则运算题第一版报告
    软件工程 1.《现代软件工程—构建之法》-概论(精读一章有感+练习与讨论部分)
    第四次博客作业-结对项目
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7602156.html
Copyright © 2020-2023  润新知