hdu 3442 Three Kingdoms


状态压缩+BFS //记忆话搜索


#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char map[55][55];
int mp[55][55];
int dp[55][55][1<<5];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int xe[5]= {1,2,3,4,5};
struct node
{
    int x, y, hp;
} st, u, v;
int abs(int x)
{
    if(x < 0)  return -x;
    return x;
}
queue < node > que;
int main()
{
    int T;
    int n, m, sx, sy, ex, ey, cas=1;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++)
        {
            scanf("%s", map[i]);
        }
        memset(mp, 0, sizeof(mp));//对图上每个点打上类型
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(map[i][j] == '#')
                {
                    mp[i][j] = -1;
                    continue;
                }
                if(map[i][j] == '$')
                {
                    sx = i;
                    sy = j;
                    continue;
                }
                if(map[i][j] == '!')
                {
                    ex = i;
                    ey = j;
                    continue;
                }
                if(map[i][j] == 'A')
                {
                    mp[i][j] = -1;//不可以踏入的
                    for(int x = -2; x < 3; x++)
                    {
                        for(int y = -2; y < 3; y++)
                        {
                            if(abs(x) + abs(y) > 2)  continue;
                            int bx = i + x;
                            int by = j + y;
                            if(bx >= 0 && bx < n && by >= 0 && by < m && mp[bx][by] != -1)
                            {
                                mp[bx][by] |= 1;
                            }
                        }
                    }
                    continue;
                }
                if(map[i][j] == 'B')
                {
                    mp[i][j] = -1;//不可以踏入的
                    for(int x = -3; x < 4; x++)
                    {
                        for(int y = -3; y < 4; y++)
                        {
                            if(abs(x) + abs(y) > 3)  continue;
                            int bx = i + x;
                            int by = j + y;
                            if(bx >= 0 && bx < n && by >= 0 && by < m && mp[bx][by] != -1)
                            {
                                mp[bx][by] |= 1 << 1;
                            }
                        }
                    }
                    continue;
                }
                if(map[i][j] == 'C')
                {
                    mp[i][j] |= 1 << 2;
                }
                if(map[i][j] == 'D')
                {
                    mp[i][j] = -1;//不可以踏入的
                    for(int x = -2; x < 3; x++)
                    {
                        for(int y = -2; y < 3; y++)
                        {
                            if(abs(x) + abs(y) > 2)  continue;
                            int bx = i + x;
                            int by = j + y;
                            if(bx >= 0 && bx < n && by >= 0 && by < m && mp[bx][by] != -1)
                            {
                                mp[bx][by] |= 1 << 3;
                            }
                        }
                    }
                    continue;
                }
                if(map[i][j] == 'E')
                {
                    mp[i][j] = -1;//不可以踏入的
                    for(int x = -1; x < 2; x++)
                    {
                        for(int y = -1; y < 2; y++)
                        {
                            if(abs(x) + abs(y) > 1)  continue;
                            int bx = i + x;
                            int by = j + y;
                            if(bx >= 0 && bx < n && by >= 0 && by < m && mp[bx][by] != -1)
                            {
                                mp[bx][by] |= 1 << 4;
                            }
                        }
                    }
                    continue;
                }
            }
        }
        /*for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                printf("%d  ",mp[i][j]);
            }
            puts("");
        }*/


        st.x = sx;
        st.y = sy;
        st.hp = 0;
        memset(dp, -1, sizeof(dp));
        dp[st.x][st.y][0] = 0;
        que.push(st);
        int a, b, c;
        while(!que.empty())
        {
            u = que.front();
            que.pop();
            for(int i = 0; i < 4; i++)
            {
                b = dp[u.x][u.y][u.hp];
                v.x = u.x + dx[i];
                v.y = u.y + dy[i];
                if(v.x>=n||v.x<0||v.y>=m||v.y<0||mp[v.x][v.y]==-1)continue;
                for(int j=0; j<5; j++)
                {
                    a=mp[v.x][v.y]&(1<<j);
                    c=u.hp&(1<<j);
                    if(a!=0&&c==0)
                    {
                        b+=xe[j];
                    }
                }
                v.hp = u.hp | mp[v.x][v.y];
                if(dp[v.x][v.y][v.hp]==-1||dp[v.x][v.y][v.hp]>b)
                {
                    dp[v.x][v.y][v.hp]=b;
                    que.push(v);
                }
            }
        }
        int ans=-1;
        for(int i=0; i< (1<<5); i++)
        {
            if(dp[ex][ey][i]!=-1 && (dp[ex][ey][i]<ans ||ans==-1))
            {
                ans=dp[ex][ey][i];
            }
        }
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值