【搜索/贪心】盘古之心

来源:互联网 发布:win7下怎么卸载Ubuntu 编辑:程序博客网 时间:2024/04/29 16:10

1. 盘古之心(maze.pas/c/cpp)

【题目描述】

蒟蒻暮雨、今夕喜欢玩一款名叫仙剑的游戏,仙剑1、2、3、4、5对他来说都毫无难度,于是他开始挑战传说中的《仙剑奇侠传3外传——问情篇》,说是问情篇,其实网上大家都是叫的“问路篇”,其中的迷宫怎一个变态了得……

好在暮雨、今夕是这方面的高手,成功攻克了一个又一个的难关,眼看就要结束了,他来到了一个名字叫做“盘古之心”的地方,这个迷宫简直是变态,它分了很多层,每一层有很多的出口,很多的机关,通向其他层(第一层可能到2、3、4、5、6层这种),最终的目标是从第一层走到最后一层,而且有些地方必须开机关才能过,甚至有可能机关不在当前层……暮雨、今夕奋斗了一下午,从1层走到了5层(囧)。

眼看着就要打最终Boss了,暮雨、今夕非常着急,想请你帮个忙。

为了减小难度,现在把地图抽象为一个矩阵,矩阵中只有一个入口,记为2,只有一个出口,记为3,可以走的地方记为0,不能走的地方记为1,机关有N个,都记为4,可以向上下左右4个方向移动,人一出来就在入口,现在需要你找出一条最短的通道通向出口,并输出可能的最小步数(默认每次移动的步数为1)。

【友情提示】

1、不出发所有的机关就不能通往下一层

2、根据常识,机关一般都在某条路的尽头,你不可能顺路就打开机关……

3、开挂是不允许的,所以不能穿墙或者在墙上走

4、默认地图上的怪都在KM命令下灰飞烟灭,不用考虑打怪问题

5、这不是以前常见的走迷宫,这是有现实意义的迷宫,路是一条一条的,有岔路,岔路的尽头是宝箱或者机关,不会出现一坨路,即不可能出现4个及其以上的0或2在一坨……

【输入格式】

输入文件maze.in,第一行为三个整数a,b,N,表示矩阵的长和宽,以及机关总数,接下来的几行,为一个N*M的矩阵,描述见题中信息

【输出格式】

输出文件maze.out,只有一行,为最小步数,无法到达终点的话,就输出“我勒个去!”(不含引号)

【输入样例】

4 4 2

4 0 1 1

1 0 2 0

1 0 1 0

3 0 1 4

【输出样例】

13

【样例解释】

路径:→↓↓↑↑←←↑←→↓↓↓←(走到终点的一瞬间就到达另一层了,所以不算在步数里面)

【数据范围】

对于60%的数据,有0<N,M<=10;

对于100%的数据,有0<N,M<=50。


标程方法是贪心,因为路的宽度是1,所以我们找到直径,然后算出所有的机关到直径的距离,加起来就是答案。

我用的搜索,状态压缩记录开关的情况,大于32,因此要用long long.

有点麻烦的是标记,我用的set,然而一开始一直不对,因为set的比较函数写错了,因为步数是不纳入比较的,否则不可能有相同的状态。

手做了几个数据改对了。


#include <cstdio>#include <cstring>#include <string>#include <set>long map[60][60];long sx;long sy;long tx;long ty;struct Sta{long x;long y;long step;long long key;bool operator<(const Sta s2)const{if (x==s2.x&&y==s2.y)return key<s2.key;if (x==s2.x)return y<s2.y;return x<s2.x; }};const long dx[] = {-1,0,1,0};const long dy[] = {0,1,0,-1};const long mod = 10000000;Sta que[mod + 10];std::set<Sta> used;long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}int main(){freopen("maze.in","r",stdin);freopen("maze.out","w",stdout);long n = getint();long m = getint();long tmp = getint();long cnt = 0;for (long i=1;i<n+1;i++){for (long j=1;j<m+1;j++){do map[i][j] = getchar();while (map[i][j]<'0'||map[i][j]>'4');map[i][j] -= '0';if (map[i][j] == 2){sx = i;sy = j;}if (map[i][j] == 3){tx = i;ty = j;}if (map[i][j] == 4){map[i][j] += (++cnt);}}}Sta now;Sta nxt;long l = 0;long r = 0;r ++;que[r].x = sx;que[r].y = sy;que[r].step = 0;que[r].key = 0;used.insert(que[r]);while (l != r){l ++;if (l > mod)l = 0;now = que[l];if (map[now.x][now.y] == 3){if (now.key == (1<<cnt)-1){printf("%ld",now.step-1);return 0;}}for (long i=0;i<4;i++){nxt.x = now.x+dx[i];nxt.y = now.y+dy[i];if (map[nxt.x][nxt.y]==1||nxt.x<1||nxt.y<1||nxt.x>n||nxt.y>m)continue;nxt.step = now.step+1;nxt.key = now.key;if (map[now.x][now.y]>4){nxt.key |= 1ll<<(map[now.x][now.y]-5);}if (used.find(nxt)==used.end()){used.insert(nxt);r ++;if (r > mod)r = 0;que[r] = nxt;}}}printf("我勒个去!");return 0;}



原创粉丝点击