记忆化搜索之一: hihoCoder 1491 : Monster Killing

微软2017年预科生计划在线编程笔试
第一场 第三题
hihoCoder #1491 : Monster Killing
http://hihocoder.com/problemset/problem/1491

可以用记忆化搜索做
参考 这篇http://blog.csdn.net/buptzhengchaojie/article/details/69831275 的思路。
下面是C++代码

#include<iostream>
#include<cstdio>
#include<cassert>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int STATE=(1<<25);
const int offset=8;
int visited[STATE*offset];

char maze[10][10];
int n,m;
int player_hp;
int player_attack;

struct Monster
{
    int hp;
    int attack;
    char type;
    unsigned mask;
    int i;
    int j;
    int cost[6];
    int buff[6];
    void set(int h,int a,char t)
    {
        hp=h;
        attack=a;
        type=t;
    }
    void cal()
    {
        for(int i=0;i<=5;i++)
        {
            int j=i;
            calcost(player_attack,j,cost[i],buff[i]);
        }
    }
    void calcost(int player_attack,int buff,int& cost ,int &buffleft)
    {
        int monster_hp=hp;
        cost=0;
        while(buff && monster_hp>0)
        {
            monster_hp-=player_attack;
            buff--;
        }
        if(monster_hp>0)
        {
            int t=(monster_hp+player_attack-1)/player_attack;
            cost+=attack*t;
        }
        if(type=='S')
        {
            buff=5;
        }
        buffleft=buff;
    }

};
Monster monsters[100];

unsigned allmask;

inline unsigned getmask(int i,int j)
{
    return 1<<(i*(m+1)+j);
}
inline unsigned neighbormask(unsigned mask)
{
    unsigned r;
    r=(mask<<(1+m))
        | (mask>>(1+m))
        | (mask>>1)
        | (mask<<1);
    return r;
}
inline unsigned getstate(int i,int j,int buff)
{
    return ((1<<(i*(m+1)+j))<<3)+buff;
}
int search(int cur)
{
    if(visited[cur]!=0)
    {
        return visited[cur];
    }
    int curmask=(cur>>3);
    int curbuff=cur&7;
    if((curmask&allmask)==allmask)
    {
        visited[cur]=1;
        return 1;
    }

    visited[cur]=player_hp+1;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            unsigned tempmask=getmask(i,j);
            if(tempmask&curmask)// visited already
            {
                continue;
            }
            unsigned neighbor=neighbormask(tempmask);
            if((neighbor&curmask)==0)// no neighbor
            {
                continue;
            }
            int tempbuff=curbuff-1;
            if(tempbuff<0)
            {
                tempbuff=0;
            }
            int cost=0;
            if(maze[i][j]=='.')//road
            {
                //buff already taken care of
            }
            else//monster
            {
                //assert(maze[i][j]=='M' || maze[i][j]=='S');
                int monster_i=maze[i][j];
                cost=monsters[monster_i].cost[tempbuff];
                tempbuff=monsters[monster_i].buff[tempbuff];
            }
            if(tempbuff<=1)
            {
                tempbuff=0;
            }
            int cost2=search(((curmask|tempmask)<<3)|tempbuff);
            int cost_total=cost2+cost;
            visited[cur]=min(visited[cur],cost_total);
        }
    }

    return visited[cur];
}


int main()
{
    int hp;
    int attack;
    int entrance_i;
    int entrance_j;

    //while(cin>>n>>m)
    cin>>n>>m;
    {
        assert((m+1)*n<=25);
        int s_c=0;
        int m_c=0;
        for(int i=0;i<n;i++)
        {
            cin>>maze[i];
        }
        int monster_len=0;
        allmask=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(maze[i][j]=='S')
                {
                    s_c++;
                    scanf("%d%d",&hp,&attack);
                    //cin>>hp>>attack;
                    maze[i][j]=monster_len;
                    monsters[monster_len++].set(hp,attack,'S');
                    allmask |= getmask(i,j);
                }
                else if(maze[i][j]=='M')
                {
                    m_c++;
                    scanf("%d%d",&hp,&attack);
                    //cin>>hp>>attack;
                    maze[i][j]=monster_len;
                    monsters[monster_len++].set(hp,attack,'M');
                    allmask |= getmask(i,j);
                }
                else if(maze[i][j]=='D')
                {
                    entrance_i=i;
                    entrance_j=j;
                }
            }
        }
        scanf("%d%d",&player_hp,&player_attack);
        //cin>>player_hp>>player_attack;
        for(int i=0;i<monster_len;i++)
        {
            monsters[i].cal();
        }

        //memset(visited,-1,sizeof(visited));
        int e=getstate(entrance_i,entrance_j,5);
        int x=player_hp-search(e)+1;
        if(x<=0)
        {
            cout<<"DEAD"<<endl;
        }
        else
        {
            cout<<x<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值