codevs 1911孤岛营救问题/2219拯救大兵瑞恩

来源:互联网 发布:微信运动微信数据来源 编辑:程序博客网 时间:2024/04/28 22:17

题目描述 Description
1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被
敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的
地形图。迷宫的外形是一个长方形,其南北方向被划分为N 行,东西方向被划分为M列,
于是整个迷宫被划分为N×M 个单元。每一个单元的位置可用一个有序数对(单元的行号,
单元的列号)来表示。南北或东西方向相邻的2 个单元之间可能互通,也可能有一扇锁着的
门,或者是一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分成P类,
打开同一类的门的钥匙相同,不同类门的钥匙不同。

大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,
在西北角。也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个
相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。
«编程任务:
试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元,营救大兵瑞恩。
输入描述 Input Description
第1行有3个整数,分别表示N,M,P的值。第2 行是1
个整数K,表示迷宫中门和墙的总数。第I+2 行(1<=I<=K),有5 个整数,依次为
Xi1,Yi1,Xi2,Yi2,Gi:
当Gi>=1时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一扇第Gi类的门,当Gi=0 时,
表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一堵不可逾越的墙(其中,|Xi1-Xi2|+|Yi1-Yi2|=1,
0<=Gi<=P)。
第K+3行是一个整数S,表示迷宫中存放的钥匙总数。
第K+3+J 行(1<=J<=S),有3个整数,依次为Xi1,Yi1,Qi:表示第J 把钥匙存放在(Xi1,Yi1)
单元里,并且第J 把钥匙是用来开启第Qi类门的。(其中1<=Qi<=P)。
输入数据中同一行各相邻整数之间用一个空格分隔。
输出描述 Output Description
将麦克营救到大兵瑞恩的最短时间的值输出。如果问题无解,则输出-1。
样例输入 Sample Input
4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
样例输出 Sample Output
14

其实这道题先前做kac的迷宫的时候接触过,但这道题稍难一些

题目大意是要在地图上有一些单元之间两两有墙,如果有相应的钥匙就可以开门(墙),但有些墙是开不了的,即使有钥匙也不行QAQ
这样的话就可以使用bfs来解决这道题
在搜索过程中保存坐标和已拥有的钥匙数
类似分层的思想,拥有不同的钥匙进行不同的bfs操作
如果可以到达终点的话即是最终答案
保存钥匙时可以使用压位操作,这样只需要3维数组就可以维护状态(某神犇开12维数组用血淋淋的教训告诉我们还是压位好用)

#include<iostream>#include<cstdio>#include<queue>using namespace std;int map[50][50];int door[50][50][50][50];bool use[50][50][50];int x_x[5]={0,0,0,1,-1};int y_y[5]={0,1,-1,0,0};struct doubi{    int x,y,k;    int g;};int n,m,p,k;queue<doubi> q;bool can(int x,int y){    if(x>=1&&x<=n&&y>=1&&y<=m){        return true;    }    return false;}bool havekey(int k,int num){    return k&(1<<num);}void addkey(int &k,int num){    k|=num;    return ;}bool flag=0;void bfs(){    doubi fuckcy;    fuckcy.x=1,fuckcy.y=1;    fuckcy.k=0,fuckcy.g=0;    use[1][1][0]=1;    q.push(fuckcy);    while(!q.empty()){        doubi facy=q.front();        q.pop();        int x=facy.x,y=facy.y;        if(x==n&&y==m){            cout<<facy.g<<endl;            flag=1;            return;        }        for(int i=1;i<=4;i++){            int X=x+x_x[i];            int Y=y+y_y[i];            doubi nxt=facy;            nxt.x=X,nxt.y=Y;            if(can(X,Y)&&!use[X][Y][facy.k]){                if(door[x][y][X][Y]==214748364) continue;                if(door[x][y][X][Y]){                    if(havekey(nxt.k,door[x][y][X][Y])){                        nxt.g=facy.g+1;                        if(map[X][Y])                        addkey(nxt.k,map[X][Y]);                        use[X][Y][nxt.k]=1;                        q.push(nxt);                    }                    else continue;                }                else{                    nxt.g=facy.g+1;                    if(map[X][Y])                    addkey(nxt.k,map[X][Y]);                    use[X][Y][nxt.k]=1;                    q.push(nxt);                }            }        }    }}int main(){    cin>>n>>m>>p;    cin>>k;    for(int i=1;i<=k;i++){        int x1,y1,x2,y2,v;        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);        if(v==0){            v=214748364;        }        door[x1][y1][x2][y2]=v;        door[x2][y2][x1][y1]=v;    }    int s;    cin>>s;    for(int i=1;i<=s;i++){        int x,y,q;        scanf("%d%d%d",&x,&y,&q);        map[x][y]|=1<<q;    }    bfs();    if(!flag){        cout<<"-1"<<endl;    }    return 0;}

顺带一提codevs拯救大兵瑞恩其中一个点的数据是错的
要想过的话还是打个表比较好= =

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 坐久了肚子胀疼怎么办 怀孕后胖的太快怎么办 怀孕牙齿全坏了怎么办 怀孕脸胖了好多怎么办 孕晚期不爱吃肉怎么办 怀孕期间胖了怎么办啊 孕期长得太胖怎么办 狗吃马肉脸肿了怎么办 狗过敏了脸肿了怎么办 孕初期外阴很痒怎么办 怀孕了吃了田鸡怎么办 孕妇睡眠质量差怎么办吃什么 39周2天了还不生怎么办 孕中期体重猛长怎么办 4个半月胎位不正怎么办 41周不产生宫缩怎么办 生完孩子胎盘没有脱落怎么办 39周还是臀位怎么办 怀孕7个月胎位不正怎么办 怀孕六个多月胎位不正怎么办 怀孕七个月了胎位不正怎么办 怀孕七个月胎位不正怎么办 怀孕肚子上有妊娠纹怎么办 怀孕九个月肚子长痱子怎么办 怀孕前体重偏胖怎么办 怀孕打胰岛素血糖控制不好怎么办 孕后期憋的难受怎么办 怀孕6个月不想生怎么办 孕六个月不想要怎么办 怀孕9个月喝酒了怎么办 怀孕8个月喝醉了怎么办 怀孕6个月胃酸烧心怎么办 怀孕7个月胃酸怎么办 怀孕5个月胃酸怎么办 怀孕2个月胃酸怎么办 怀孕六个月胃酸烧心怎么办 孕六个月反胃酸怎么办 怀孕三个月胃酸吐酸水怎么办 孕六个月胃难受怎么办 孕6个月胃酸厉害怎么办 孕妇6个月胃酸怎么办