多灾多难的公主又被大魔王抓走啦!国王派遣了第一勇士蒜头君去拯救她。身为超级厉害的术士,同时也是蒜头君的好伙伴,你决定祝他一臂之力。你为蒜头君提供了一张大魔王根据地的地图,上面标记了蒜头君和公主所在的位置,以及一些不能够踏入的禁区。你还贴心地为蒜头君制造了一些传送门,通过一个传送门可以瞬间转移到任意一个传送门,当然蒜头君也可以选择不通过传送门瞬移。传送门的位置也被标记在了地图上。此外,你还查探到公主所在的地方被设下了结界,需要集齐 K(0≤K≤5) 种宝石才能打开。当然,你在地图上也标记出了不同宝石所在的位置。你希望蒜头君能够带着公主早日凯旋。于是在蒜头君出发之前,你还需要为蒜头君计算出他最快救出公主的时间。地图用一个 R×C 的字符矩阵来表示。字符 S 表示蒜头君所在的位置,字符 E 表示公主所在的位置,字符 # 表示不能踏入的禁区,字符 $ 表示传送门,字符 . 表示该位置安全,数字字符 0 至 4 表示了宝石的类型。蒜头君每次可以从当前的位置走到他上下左右四个方向上的任意一个位置,但不能走出地图边界。蒜头君每走一步需要花费 1 个单位时间,从一个传送门到达另一个传送门不需要花费时间。当蒜头君走到宝石所在的位置时,就视为得到了该宝石,不需要花费额外时间。
输入格式第一行是一个正整数 T(1≤T≤10),表示一共有 T 组数据。 每一组数据的第一行包含了三个用空格分开的正整数 R、C(2≤R,C≤200) 和 K,表示地图是一个 R×C的矩阵,而蒜头君需要集齐 KKK 种宝石才能够打开拘禁公主的结界。 接下来的 R 行描述了地图的具体内容,每一行包含了 C 个字符。字符含义如题目描述中所述。保证有且仅有一个 S 和 E。$ 的数量不超过 10 个。宝石的类型在数字 0 至 4 范围内,即不会超过 5 种宝石。
输出格式对于每一组数据,输出蒜头君救出公主所花费的最少单位时间。若蒜头君无法救出公主,则输出 “oop!”(只输出引号里面的内容,不输出引号)。每组数据的输出结果占一行。
1
7 8 2
........
..S..#0.
.##..1..
.0#.....
...1#...
...##E..
...1....
11
//拯救公主-内存超限写法
#include
#include
#include
#include
using namespace std;
struct muban
{
int x;
int y;
int num;
int time;
}que[45000];
char imap[205][205];
int book[205][205][11114];
int s[11][2];
int inext[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int ichange(int x,char shu)
{
int q=shu-'0';
int num=1;
while(q--)
num*=10;
x+=num;
return x;
}
int judge(int x,char shu)
{
int q=shu-'0';
while(q--)
{
x=x/10;
}
x=x%10;
if(x==1)
return 1;
else if(x==0)
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(book,0,sizeof(book));
int n,m,k,num_s;
cin>>n>>m>>k;
int stax,stay,endx,endy;
num_s=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>imap[i][j];
if(imap[i][j]=='S')
{
stax=i;
stay=j;
}
if(imap[i][j]=='$')
{
s[num_s][0]=i;
s[num_s][1]=j;
num_s++;
}
}
}
int bao_num=1;
if(k==0)
bao_num=0;
else
{
for(int i=1;i<k;i++)
bao_num=bao_num*10+1;
}
int tx,ty,tn,tt,min_time,head,tail;
head=1;
tail=2;
que[head].x=stax;
que[head].y=stay;
que[head].num=0;
que[head].time=0;
book[stax][stay][0]=1;
min_time=40005;
while(head<tail)
{
for(int i=0;i<4;i++)
{
tx=que[head].x+inext[i][0];
ty=que[head].y+inext[i][1];
tn=que[head].num;
tt=que[head].time;
if(tx>=0&&tx<n&&ty>=0&&ty<m)
{
if(book[tx][ty][tn]==0&&imap[tx][ty]=='.')
{
que[tail].x=tx;que[tail].y=ty;
que[tail].time=tt+1;
que[tail].num=tn;
book[tx][ty][tn]=1;
tail++;
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]>='0'&&imap[tx][ty]<='4')
{
que[tail].x=tx;que[tail].y=ty;
que[tail].time=tt+1;
book[tx][ty][tn]=1;
if(judge(que[head].num,imap[tx][ty])==0)//如果这个宝石没有捡起
que[tail].num=ichange(que[head].num,imap[tx][ty]);
else
que[tail].num=que[head].num;
tail++;
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]=='$')
{
que[tail].x=tx;que[tail].y=ty;que[tail].num=tn;
que[tail].time=tt+1;
book[tx][ty][tn]=1;
tail++;
for(int j=0;j<num_s;j++)
{
if(book[s[j][0]][s[j][1]][tn]==0)//对于每一个传送门要再进行判断
{
que[tail].x=s[j][0];
que[tail].y=s[j][1];
que[tail].time=tt+1;
que[tail].num=tn;
book[s[j][0]][s[j][1]][tn]=1;
tail++;
}
}
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]=='E'&&que[head].num==bao_num)
{
if(que[head].time+1<min_time)
min_time=que[head].time+1;
}
}
}
head++;
}
if(min_time==40005)
cout<<"oop!"<<endl;
else
cout<<min_time<<endl;
}
return 0;
}
AC代码如下:
#include
#include
#include
#include
using namespace std;
struct muban
{
int x;
int y;
int num;
int time;
}que[95000];
char imap[205][205];
int book[205][205][35];
int s[11][2];
int inext[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n,m,k,qq,num_s;
int judge(int x)
{
int num=0;
for(int i=0;i<5;i++)
{
if((x>>i)&1)
num++;
}
if(num>=k)
return 1;
else
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(book,0,sizeof(book));
qq=0;//记录宝石个数
num_s=0;//记录传送门个数
cin>>n>>m>>k;
int stax,stay,endx,endy;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>imap[i][j];
if(imap[i][j]=='S')
{
stax=i;
stay=j;
}
if(imap[i][j]=='$')
{
s[num_s][0]=i;
s[num_s][1]=j;
num_s++;
}
if(imap[i][j]>='0'&&imap[i][j]<='9')
qq++;
}
}
if(k>qq)
{
cout<<"oop!"<<endl;
continue;
}
int tx,ty,tn,tt,min_time,head,tail;
head=1;
tail=2;
que[head].x=stax;
que[head].y=stay;
que[head].num=0;
que[head].time=0;
book[stax][stay][0]=1;
min_time=40005;
while(head<tail)
{
for(int i=0;i<4;i++)
{
tx=que[head].x+inext[i][0];
ty=que[head].y+inext[i][1];
tn=que[head].num;
tt=que[head].time;
if(tx>=0&&tx<n&&ty>=0&&ty<m)
{
if(book[tx][ty][tn]==0&&imap[tx][ty]=='.')
{
que[tail].x=tx;que[tail].y=ty;
que[tail].time=tt+1;
que[tail].num=tn;
book[tx][ty][tn]=1;
tail++;
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]>='0'&&imap[tx][ty]<='4')
{
que[tail].x=tx;que[tail].y=ty;
que[tail].time=tt+1;
book[tx][ty][tn]=1;
que[tail].num=tn|(1<<(imap[tx][ty]-'0'));
tail++;
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]=='$')
{
que[tail].x=tx;que[tail].y=ty;que[tail].num=tn;
que[tail].time=tt+1;
book[tx][ty][tn]=1;
tail++;
for(int j=0;j<num_s;j++)
{
if(book[s[j][0]][s[j][1]][tn]==0)//对于每一个传送门要再进行判断
{
que[tail].x=s[j][0];
que[tail].y=s[j][1];
que[tail].time=tt+1;
que[tail].num=tn;
book[s[j][0]][s[j][1]][tn]=1;
tail++;
}
}
}
else if(book[tx][ty][tn]==0&&imap[tx][ty]=='E'&&judge(tn)==1)
{
if(que[head].time+1<min_time)
min_time=que[head].time+1;
}
}
}
head++;
}
if(min_time==40005)
cout<<"oop!"<<endl;
else
cout<<min_time<<endl;
}
return 0;
}