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;
}
原文地址:https://www.cnblogs.com/zbtrs/p/7602156.html