nyist 999 师傅又被妖怪抓走了 【双广搜 || BFS +状态压缩】

题目:nyist 999 师傅又被妖怪抓走了


分析:在一个图中只要看到D点和E点就行的最小步数,看到的定义是:也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。

所以可以先预处理地图,把D点和E点所在的行列的‘ .’扩展为d和e,然后只要搜到d和e就可以,问题是只有d和e同时搜到才行,直接广搜肯定不行,我们可以在搜到d点之后然后在从当前点广搜e点,或者e点广搜d点,这样第一次搜到的点不一定是最优的,所以需要枚举所有情况才行,时间复杂度较高。


比较好的一种方法是BFS+状态压缩,定义dp【i】【j】【st】:如果搜到e,状态变化dp【i】【j】【01】,重新初始化图标记,再搜,然后搜到d则dp【i】【j】【10】,知道dp【i】【j】【11】是step就是最小的。这样复杂度较低

BFS+状态压缩

 
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define INT long long
#define Del(a,b) memset(a,b,sizeof(a))
const INT inf =  0x3f3f3f3f;
const int N = 120;
int mp[N][N];
bool vis[N][N][4];
int n,m,t;
int ans;
struct Node
{
    int x,y;
    int step,st;
};
int dx[5]= {0,0,1,-1};
int dy[5]= {1,-1,0,0};
bool check(int x,int y)
{
    if(mp[x][y]=='X' || mp[x][y]=='D' || mp[x][y]=='E')
        return false;
    return true;
}
char solve(char x,int ok)
{
    if(ok && x=='e' || !ok && x=='d')
        return 'y';
    return ok?'d':'e';
}
void isit(int x,int y,int ok)
{
    for(int i=x+1; i<m && check(i,y); i++)
        mp[i][y]=solve(mp[i][y],ok);
    for(int i=x-1; i>=0 && check(i,y); i--)
        mp[i][y] = solve(mp[i][y],ok);
    for(int j=y+1; j<n && check(x,j); j++)
        mp[x][j] = solve(mp[x][j],ok);
    for(int j=y-1; j>=0 && check(x,j); j--)
        mp[x][j] = solve(mp[x][j],ok);
}
int ST_solve(char x,int st)
{
    if(x=='d')
        st|=1;
    else if(x=='e')
        st|=2;
    else if(x=='y')
        st|=3;
    return st;
}
void BFS(Node s)
{
    s.step = 0;
    s.st = ST_solve(mp[s.x][s.y],0);
    Del(vis,0);
    queue<Node> q;
    q.push(s);
    vis[s.x][s.y][s.st]=1;
    while(!q.empty())
    {
        Node x = q.front(),f;
        q.pop();
        if(x.st==3)
        {
            ans = x.step;
            return ;
        }
        for(int i=0; i<4; i++)
        {
            f.x = x.x + dx[i];
            f.y = x.y + dy[i];
            f.step = x.step + 1;
            f.st = x.st;
            if(check(f.x,f.y) && vis[f.x][f.y][f.st]==0 && f.x>=0 && f.y>=0 && f.x<n && f.y<m)
            {
                f.st = ST_solve(mp[f.x][f.y],f.st);
                vis[f.x][f.y][f.st]=1;
                q.push(f);
            }
        }
    }
}
int main()
{
    int cas=1;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        Del(mp,0);  //记得初始化
        Node s;
        for(int i=0; i<n; i++)
        {
            getchar();
            for(int j=0; j<m; j++)
            {
                scanf("%c",&mp[i][j]);
                if(mp[i][j]=='S')
                    s.x=i,s.y=j;
            }
        }
        for(int i=0; i<n; i++) //预处理
        {
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='D')
                    isit(i,j,1);
                else if(mp[i][j]=='E')
                    isit(i,j,0);
            }
        }
        ans = inf;
        BFS(s);
        printf("Case %d:\n",cas++);
        if(ans<=t)
            printf("%d\n",ans);
        else
            puts("-1");
    }
    return 0;
}
        


双广搜AC代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define INT long long
#define Del(a,b) memset(a,b,sizeof(a))
const INT inf =  0x3f3f3f3f;
const int N = 120;
int mp[N][N];
bool vis[N][N],css[N][N];
int n,m,t;
int ans;  //标记
struct Node
{
    int x,y;
    int step;
};
int dx[5]= {0,0,1,-1};
int dy[5]= {1,-1,0,0};
bool check(int x,int y)
{
    if(mp[x][y]=='X' || mp[x][y]=='D' || mp[x][y]=='E')
        return false;
    return true;
}
char solve(char x,int ok)
{
    if(ok && x=='e' || !ok && x=='d')
        return 'y';
    return ok?'d':'e';
}
void isit(int x,int y,int ok)
{
    for(int i=x+1; i<m && check(i,y); i++)
        mp[i][y]=solve(mp[i][y],ok);
    for(int i=x-1; i>=0 && check(i,y); i--)
        mp[i][y] = solve(mp[i][y],ok);
    for(int j=y+1; j<n && check(x,j); j++)
        mp[x][j] = solve(mp[x][j],ok);
    for(int j=y-1; j>=0 && check(x,j); j--)
        mp[x][j] = solve(mp[x][j],ok);
}
int BFS2(Node s,int ok)
{
    Del(css,0);
    queue<Node> f;
    f.push(s);
    css[s.x][s.y]=1;
    while(!f.empty())
    {
        Node x = f.front(),tmp;
        f.pop();
        if(ok && mp[x.x][x.y]=='e' || !ok && mp[x.x][x.y]=='d')
            return x.step;
        for(int i=0;i<4;i++)
        {
            tmp.x = x.x + dx[i];
            tmp.y = x.y + dy[i];
            tmp.step = x.step + 1;
            if(check(tmp.x,tmp.y) && css[tmp.x][tmp.y]==0 && tmp.x>=0 && tmp.y>=0 && tmp.x<n && tmp.y<m)
            {
                css[tmp.x][tmp.y]=1;
                f.push(tmp);
            }
        }
    }
    return inf;
}
void BFS(Node s)
{
    s.step = 0;
    Del(vis,0);
    queue<Node> q;
    q.push(s);
    vis[s.x][s.y]=1;
    while(!q.empty())
    {
        Node x = q.front(),f;
        q.pop();
        if(mp[x.x][x.y]=='y')
            ans = min(ans,x.step);
        else if(mp[x.x][x.y]=='d'){
            int fff = BFS2(x,1);
            ans = min(ans,fff);
        }
        else if(mp[x.x][x.y]=='e')
        {
            int eee = BFS2(x,0);
            ans = min(ans,eee);
        }
        for(int i=0; i<4; i++)
        {
            f.x = x.x + dx[i];
            f.y = x.y + dy[i];
            f.step = x.step + 1;
            if(check(f.x,f.y) && vis[f.x][f.y]==0 && f.x>=0 && f.y>=0 && f.x<n && f.y<m)
            {
                vis[f.x][f.y]=1;
                q.push(f);
            }
        }
    }
}
int main()
{
    int cas=1;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        Del(mp,0);  //记得初始化
        Node s;
        for(int i=0; i<n; i++)
        {
            getchar();
            for(int j=0; j<m; j++)
            {
                scanf("%c",&mp[i][j]);
                if(mp[i][j]=='S')
                    s.x=i,s.y=j;
            }
        }
        for(int i=0; i<n; i++) //预处理
        {
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='D')
                    isit(i,j,1);
                else if(mp[i][j]=='E')
                    isit(i,j,0);
            }
        }
        ans = inf;
        BFS(s);
        printf("Case %d:\n",cas++);
        if(ans<=t)
            printf("%d\n",ans);
        else
            puts("-1");
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是可以实现该显示内容的代码: ``` #include <reg51.h> #define LCD_DB P0 sbit RS = P2^6; sbit RW = P2^5; sbit E = P2^7; void delay(int time) // 延时函数 { int i, j; for(i = 0; i < time; i++) for(j = 0; j < 120; j++); } void write_command(unsigned char command) // 写指令函数 { RS = 0; RW = 0; LCD_DB = command; E = 1; delay(1); E = 0; } void write_data(unsigned char data) // 写数据函数 { RS = 1; RW = 0; LCD_DB = data; E = 1; delay(1); E = 0; } void init_lcd() // 初始化液晶屏函数 { write_command(0x38); // 8位数据总线,双行显示,5x7点阵字符 write_command(0x0c); // 显示开,光标不显示,光标闪烁不显示 write_command(0x06); // 光标右移,字符不移动 write_command(0x01); // 清屏 } void display_string(unsigned char x, unsigned char y, unsigned char *s) // 在指定位置显示字符串函数 { unsigned char i; if(x < 16) { x |= 0x80; switch(y) { case 0: y = 0x80; break; case 1: y = 0x90; break; case 2: y = 0x88; break; case 3: y = 0x98; break; } write_command(y); delay(5); write_command(x); delay(5); for(i = 0; s[i] != '\0'; i++) { write_data(s[i]); delay(5); } } } void main() { init_lcd(); // 初始化液晶屏 display_string(4, 0, "南阳理工学院"); // 第一行居中显示“南阳理工学院” display_string(3, 1, "www.nyist.edu.cn"); // 第二行居中显示“www.nyist.edu.cn” display_string(4, 2, "电子信息工程专业"); // 第三行居中显示“电子信息工程专业” display_string(4, 3, "尚春芳"); // 第四行居中显示尚春芳 while(1); } ``` 需要注意的是,该代码假设你已经连接好了单片机和液晶屏,并将液晶屏的数据线接到了单片机的P0口,将液晶屏的控制线RS、RW、E分别接到了单片机的P2.6、P2.5、P2.7口。如果你的连接方式不同,需要修改代码中对应的引脚定义。另外,该代码使用的是汇编延时,如果你使用的是C语言编写,需要自行修改延时函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值