很有意思的一道题,就是迷宫问题的增强版。但是细节很多,有一个技巧就是把每个可以走的位置编号方便状态判重。

AC代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxs=20;
const int maxn=150;
const int dx[]={1,-1, 0, 0, 0};
const int dy[]={0, 0, 1,-1, 0};
int s[3],t[3];
int deg[maxn], G[maxn][5];
int d[maxn][maxn][maxn]; //记录步数
struct node //记录状态
{
    int a,b,c;
    node(int x,int y,int z):a(x),b(y),c(z){}
};

bool conflict(int a,int b,int a1,int b1)
{
    return a1==b1||(a1==b&&b1==a); //判断是否移动到同一个格子或者在一步中互换了位置
}

int bfs()
{
    queue<node>q;
    memset(d,-1,sizeof(d));
    d[s[0]][s[1]][s[2]]=0;
    q.push(node(s[0],s[1],s[2]));
    while(!q.empty())
    {
        node u=q.front(); q.pop();
        int a=u.a,b=u.b,c=u.c;
        if(a==t[0]&&b==t[1]&&c==t[2]) return d[a][b][c];
        //开始移动,移动时需要判断是否移动到同一个位置
        for(int i=0;i<deg[a];++i)
        {
            int a1=G[a][i];
            for(int j=0;j<deg[b];++j)
            {
                int b1=G[b][j];
                if(conflict(a,b,a1,b1)) continue;
                for(int k=0;k<deg[c];++k)
                {
                    int c1=G[c][k];
                    if(conflict(a,c,a1,c1)) continue;
                    if(conflict(b,c,b1,c1)) continue;
                    if(d[a1][b1][c1]!=-1)   continue;
                    d[a1][b1][c1]=d[a][b][c]+1;
                    q.push(node(a1,b1,c1));
                }
            }
        }
    }
}

int main()
{
    int w, h, n;
    while(scanf("%d%d%d\n",&w,&h,&n)==3&&w!=0)
    {
        char res[maxs][maxs];
        for(int i=0;i<h;++i) fgets(res[i],20,stdin);

        int cnt=0;
        int x[maxn],y[maxn],id[maxs][maxs];
        //给每个空格编号,很好的技巧,可以提高状态转换、判重的效率
        for(int i=0;i<h;++i)
        for(int j=0;j<w;++j)
        {
            if(res[i][j]!='#')
            {
                x[cnt]=i;y[cnt]=j;id[i][j]=cnt;
                if(islower(res[i][j])) s[res[i][j]-'a']=cnt;
                else if(isupper(res[i][j])) t[res[i][j]-'A']=cnt;
                ++cnt;
            }
        }

        for(int i=0;i<cnt;++i)
        {
            deg[i]=0;
            for(int dir=0;dir<5;++dir)
            {
                int px=x[i]+dx[dir],py=y[i]+dy[dir];
                if(px<0||px>=h||py<0&&py>=w) continue;
                if(res[px][py]!='#') G[i][deg[i]++]=id[px][py]; //当前空格的临近空格
            }
        }
        //为了简化代码,给少于三个鬼的情况增加到三个点,新增的点被处理为无法移动。
        if(n<=2) {deg[cnt] = 1; G[cnt][0] = cnt; s[2]=t[2]=cnt++;}
        if(n<=1) {deg[cnt] = 1; G[cnt][0] = cnt; s[1]=t[1]=cnt++;}

        printf("%d\n",bfs());
    }

    return 0;
}

如有不当之处欢迎指出!!

UVA1601 状态搜索的更多相关文章

  1. ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 A、Saving Tang Monk II 【状态搜索】

    任意门:http://hihocoder.com/problemset/problem/1828 Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制:25 ...

  2. UVALive 6255 Kingdoms --状态搜索

    题意:n个国家,给出国家间相互的债务关系,每个国家如果债务>收入就要破产,破产后该国的所有债务关系全部清除,第一个破产的国家不同有可能造成最后的没破产的国家的不同,问哪些国家有可能成为独自存活的 ...

  3. 用BFS和DFS解决圆盘状态搜索问题

    人工智能课程的实验(我的解法其实更像是算法课程的实验) 用到的算法:深度优先搜索.宽度优先搜索(状态扩展的不同策略) 数据结构:表示状态的结构体.多维数组 (可能是最近做算法竞赛题的影响,这次并不像以 ...

  4. Oj 24260: Lilypad Pond (神奇广搜题,状态搜索)

    题目 为了让奶牛们娱乐和锻炼,约翰建造了一个美丽的池塘.这个池塘是矩形的,可以分成M×N个方格.一些格子是坚固得令人惊讶的莲花,还有一些是岩石,其余的只是美丽,纯净,湛蓝的水.贝西正在练习芭蕾舞,她站 ...

  5. BFS + 状态搜索

    题目 题意 给一个100x100的迷宫,'.'表示路面,'S'表示起点,'T'表示终点:'#'表示毒气区,进入毒气区必须要消耗一个氧气:'B'表示氧气区,每次进入自动获得一个氧气,可反复进入从而获得多 ...

  6. laravel使用when搜索遇到状态参数(有0的状态)的坑

    今天,使用when()方法写活动列表的接口,有两个状态搜索,都有0这个状态,当传参为0时when()就失效了... 反反复复的验证参数,传参确实是0和1啊...百思不得其解~~~后面仔细想想when( ...

  7. [学习笔记]搜索——模拟与dp的结合

    搜索: 一种基础的算法. 考察常见于NOIP 但是高级的搜索算法可能还会在省选出现. 50%以上的暴力都可以用搜索直接枚举来写. 但是,当数据规模不是很大的时候,搜索也可能成为正解. (比如剪枝PK状 ...

  8. Button Bashing(搜索)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAx8AAAI2CAIAAAC+EqK4AAAgAElEQVR4nOydf0BT9f7/37fS423mWn

  9. POJ2676 (数独问题 + DLX + 状态优化顺序)

    (1)最简单的最是去暴力DFS搜索答案 , 很容易想到 , 每行每列的方式去搜索 , 不过效率是真的不行;但这个还是给出代码 ,毕竟打了也不容易呀! #include<cstdio> #i ...

随机推荐

  1. Django_生产环境静态文件配置

    需求: 当Django项目运行在线上的时候,需要关闭debug模式,那么Django设置中,静态文件路径配置将会失效,如何解决这个问题? 问题原因: Django默认关闭debug模式,Django错 ...

  2. 如何导入css和js?

    导入css <link rel="stylesheet" href="css路径" type="text/css"> 导入js, ...

  3. 流API--流的映射

    很多时候,将一个流的元素映射到另外一个流很有帮助.映射操作最具代表的就是map()方法.实际编码中,我们会经常用到,所以这里专门整理一篇博客. 考虑如下情景,对于一个包含了姓名,电话,年龄等属性构成的 ...

  4. linkin大话面向对象--包和导入

    我们现在的代码都扔在一个文件夹里面,比如以后我们做项目,是不是有可能有非常非常多的代码,那我就希望把不同功能和模块的类方便管理,放到不同的文件夹下,引出包概念. 什么是包,就一个文件目录,为了处理重名 ...

  5. JavaSE基础篇—MySQL三大范式—数据库设计规范

    1.概   念     范式是一种符合设计要求的总结,要想设计一个结构合理的关系型数据库,必须满足一定的范式.各个范式是以此嵌套包含的,范式越高,设计等级越高,在现实设计中也越难实现,一般数据库只要打 ...

  6. 服务器开发之CGI后门

    1.html代码 <form id = "form" name="form" method="post" action=". ...

  7. mvn 手动安装jar 到本地库

    安装: mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.1.0.7.0 -Dpackagi ...

  8. salesforce零基础学习(八十六)Ajax Toolkit (VF页面中使用及javascript action使用)

    Ajax Toolkit 参考文档:https://resources.docs.salesforce.com/212/latest/en-us/sfdc/pdf/apex_ajax.pdf 在项目中 ...

  9. bzoj 3996: [TJOI2015]线性代数 [最小割]

    3996: [TJOI2015]线性代数 题意:给出一个NN的矩阵B和一个1N的矩阵C.求出一个1*N的01矩阵A.使得 \(D=(A * B-C)* A^T\)最大.其中A^T为A的转置.输出D.每 ...

  10. BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

    传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边 ...