微软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;
}