SDUT oj 2193 救基友记3

一个简单的搜索题了

不过有钥匙开门什么的其他条件

(好吧这都不是重点


这题一般的做法应该是状态压缩

就是用一个小于1024的整数的二进制的位来表示当前持有的钥匙

然后检查当前位置的那个数组(我这里叫che

的第三维也开到1024

这样的话每个持有钥匙的状态都对应了这个数组的某一层

其他的就是位运算了

以下是代码

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int dir[4][2]={0,1,0,-1,1,0,-1,0};
bool che[25][25][1024];
char arr[25][25];
int key[10];
int dor[10];
int n,m,t;


struct state{
    int x;
    int y;
    int time;
    int tk;
    bool can(int k){
        x+=dir[k][0];
        y+=dir[k][1];
        time++;
        if(time>=t)
            return false;
        if(x<0 || x>=n || y<0 || y>=m || arr[x][y]=='*')
            return false;
        if(che[x][y][tk])
            return false;
        if('A'<=arr[x][y] && arr[x][y]<='J')
            if((tk|dor[arr[x][y]-'A'])!=key[10]){
                return false;
            }
        if('a'<=arr[x][y] && arr[x][y]<='j')
            tk=tk|key[arr[x][y]-'a'];

        che[x][y][tk]=true;
        return true;
    }
};

void fnd(state &p){
    for(p.x=0;p.x<n;p.x++)
        for(p.y=0;p.y<m;p.y++)
            if(arr[p.x][p.y]=='@')
                return;
}

int dfs(){
    state s;
    fnd(s);
    s.time=0;
    s.tk=0;
    queue<state> q;
    q.push(s);
    while(q.empty()==false){
        s=q.front();
        if(arr[s.x][s.y]=='^')
            return s.time;
        for(int i=0;i<4;i++){
            s=q.front();
            if(s.can(i))
                q.push(s);
        }
        q.pop();
    }
    return -1;
}

int main(){
    key[0]=1;
    for(int i=1;i<=10;i++)
        key[i]=key[i-1]*2;
    key[10]--;
    for(int i=0;i<10;i++)
        dor[i]=key[10]-key[i];
  //  #define DEBUG
    #ifdef DEBUG
        for(int i=0;i<=10;i++)
            printf(i<10?"%d ":"%d\n",key[i]);
        for(int i=0;i<=9;i++)
            printf(i<9?"%d ":"%d\n",dor[i]);
    #endif // DEBUG
    while(~scanf("%d %d %d",&n,&m,&t)){
        for(int i=0;i<n;i++)
            scanf("%s",arr[i]);
        memset(che,0,sizeof(che));
        printf("%d\n",dfs());
    }
    return 0;
}


其实吧,这不是我第一次的想法

刚开始就觉得没有必要开到1024这么多

优化过之后只要开到11就好了

(算了我还是直接说方法好了


这是从o(2^n)到o(n)的优化(虽然只是空间复杂度)


和上一份代码不同

这里的钥匙用一个bool数组表示

为真说明你带了这把钥匙

这里che数组的每一层都唯一对应着一个钥匙

那么che[x][y][k]为TRUE代表的含义是在(x,y)这个位置你带着第k把钥匙来过了

那么如果你身上的钥匙如果不增加的话,这个地方就不值得来了

大体就是这样

每次移动的时候检查这个che数组的每一层

如果你有对应的钥匙而且有你没去过的,那么可以走

不然你都带着钥匙来过了,就不用再来了

还有要注意的是刚出发的时候你没有钥匙

所以要另外设置一个虚拟钥匙(否则你刚出来就动不了了

(想一想,为什么

以上


-----------------------------------------------我是代码的分界线----------------------


#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int dir[4][2]={0,1,0,-1,1,0,-1,0};
bool che[25][25][11];
char arr[25][25];
int dor[10];
int n,m,t;


struct state{
    int x;
    int y;
    int time;
    bool key[11];
    bool can(int k){
        x+=dir[k][0];
        y+=dir[k][1];
        time++;
        if(time>=t)
            return false;
        if(x<0 || x>=n || y<0 || y>=m || arr[x][y]=='*')
            return false;
        bool flag=true;
        for(int i=0;i<=10;i++)
            flag=flag && !(key[i] && !che[x][y][i]);
        if(flag)
            return false;
        if('A'<=arr[x][y] && arr[x][y]<='J')
            if(!key[arr[x][y]-'A']){
                return false;
            }
        if('a'<=arr[x][y] && arr[x][y]<='j')
            key[arr[x][y]-'a']=true;
        for(int i=0;i<=10;i++)
            if(key[i])
                che[x][y][i]=true;
        return true;
    }
};

void fnd(state &p){
    for(p.x=0;p.x<n;p.x++)
        for(p.y=0;p.y<m;p.y++)
            if(arr[p.x][p.y]=='@')
                return;
}

int dfs(){
    state s;
    fnd(s);
    s.time=0;
    for(int i=0;i<=9;i++)
        s.key[i]=false;
    s.key[10]=true;
    queue<state> q;
    q.push(s);
    while(q.empty()==false){
        s=q.front();
        if(arr[s.x][s.y]=='^')
            return s.time;
        for(int i=0;i<4;i++){
            s=q.front();
            if(s.can(i))
                q.push(s);
        }
        q.pop();
    }
    return -1;
}

int main(){
    while(~scanf("%d %d %d",&n,&m,&t)){
        for(int i=0;i<n;i++)
            scanf("%s",arr[i]);
        memset(che,0,sizeof(che));
        printf("%d\n",dfs());
    }
    return 0;
}

-------------------------------------------------------------

其实这个优化是只是用时间换空间  (谢柴爷提醒

每次判断都加了一个o(s)  (s是钥匙的数量

的扫描



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值