1.29数据与结构算法学习日记

# 路障

## 题目描述

B 君站在一个 $n\times n$ 的棋盘上。最开始,B君站在 $(1,1)$ 这个点,他要走到 $(n,n)$ 这个点。

B 君每秒可以向上下左右的某个方向移动一格,但是很不妙,C 君打算阻止 B 君的计划。

**每秒结束的时刻**,C 君 会在 $(x,y)$ 上摆一个路障。B 君不能走在路障上。

B 君拿到了 C 君准备在哪些点放置路障。所以现在你需要判断,B 君能否成功走到 $(n,n)$。

**保证数据足够弱:也就是说,无需考虑“走到某处然后被一个路障砸死”的情况,因为答案不会出现此类情况。**

## 输入格式

首先是一个正整数 $T$,表示数据组数。

对于每一组数据:

第一行,一个正整数 $n$。

接下来 $2n-2$ 行,每行两个正整数 $x$ 和 $y$,意义是在那一秒结束后,$(x,y)$ 将被摆上路障。

## 输出格式

对于每一组数据,输出 `Yes` 或 `No`,回答 B 君能否走到 $(n,n)$。

## 样例 #1

### 样例输入 #1

```
2

2
1 1
2 2

5
3 3
3 2
3 1
1 2
1 3
1 4
1 5
2 2
```

### 样例输出 #1

```
Yes
Yes
```

## 提示

样例解释:

以下 0 表示能走,x 表示不能走,B 表示 B 君现在的位置。从左往右表示时间。

```
Case 1:
0 0    0 0    0 B  (已经走到了)
B 0    x B    x 0
```
```
Case 2:
0 0 0 0 0    0 0 0 0 0    0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 0 0 0    0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 x 0 0    0 0 x 0 0    0 0 x 0 0
0 0 0 0 0    0 0 0 0 0    0 0 x 0 0    0 0 x 0 0
B 0 0 0 0    0 B 0 0 0    0 0 B 0 0    0 0 x B 0 ......(B君可以走到终点)
```

数据规模:

防止骗分,数据保证全部手造。

对于 $20\%$ 的数据,有 $n\le3$。

对于 $60\%$ 的数据,有 $n\le500$。

对于 $100\%$ 的数据,有 $n\le1000$。

对于 $100\%$ 的数据,有 $T\le10$。

题目分析

1.判断B君是否可以走到终点,此处选择用bfs算法来解决

2.需要注意的是此题“每秒结束的时刻”这时c君才开始放路障

3.我们选择用一个变量t来代表时间秒数,用一个结构体数组来存放要放置的路障的坐标,每当秒数增加,对应的路障也会增加,为表示路障增加的过程,我们选择在对应路障增加时,相应的标记数组变为1意思是不能走

4.还有个注意点,每次循环一组数据完过后(毕竟有t组数据)所以应该把标记数组和路障存放数组还有队列重置

5.每次bfs时应该判断能走的路里是否有(n,n)坐标相当于循环判断队列数组里是否有(n,n)坐标所以我们队列数组也应该是结构体数组

代码示例

#include
using namespace std;
int dx[4]= {1,0,-1,0},dy[4]= {0,1,0,-1},nx,ny,T,n,x,y;
struct stu
{
    int x;
    int y;
} que[10000010],no[1001];//定义结构体数组que和no  no是路障存放数组
bool pd[1001][1001];//标记数组
void bfs()
{
    int t=1;
    int head=1;
    int tail=2;
    pd[1][1]=1;
    que[head].x=1;
    que[head].y=1;//初始化队列
  while(head=1&&ny>=1&&nx<=n&&ny<=n&&pd[nx][ny]==0)//判断这个节点是否可以走
                {que[tail].x=nx;//能走的话就把坐标入队
               que[tail].y=ny;
               pd[nx][ny]=1;
                tail++;}

        }
        head++;//在他已经能走的节点道路上接着循环找是否还有可以走的路(已经能走的节点在上一个for已经找出来了)
        pd[no[t].x][no[t].y]=1;//为下一次判断增加路障,所以下一次判断是否能走会是在路障更新后的判断
        t++;//    秒数增加

    }
    for(int i=tail; i>=1; i--)//寻找能走的路中有没有目标坐标
    {
        if(que[i].x==n&&que[i].y==n)
           { printf("Yes\n");
            return;

           }
    }
    printf("No\n");
    return;
}
void rest()//重置清空
{
    memset(que,0,sizeof(que));
    memset(pd,0,sizeof(pd));
    memset(no,0,sizeof(no));

}
int main()
{
    scanf("%d",&T);
    for(int i=0; i

题目描述

M 海运公司最近要对旗下仓库的货物进出情况进行统计。目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志。该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量;第二类操作为集装箱的出库操作。这些记录都严格按时间顺序排列。集装箱入库和出库的规则为先进后出,即每次出库操作出库的集装箱为当前在仓库里所有集装箱中最晚入库的集装箱。

出于分析目的,分析人员在日志中随机插入了若干第三类操作――查询操作。分析日志时,每遇到一次查询操作,都要报告出当前仓库中最大集装箱的重量。

输入格式

包含 N+1 行:

第一行为一个正整数 N,对应于日志内所含操作的总数。

接下来的 N 行,分别属于以下三种格式之一:

  • 格式 1:0 X,表示一次集装箱入库操作,正整数 X 表示该次入库的集装箱的重量。
  • 格式 2:1,表示一次集装箱出库操作,(就当时而言)最后入库的集装箱出库。
  • 格式 3:2,表示一次查询操作,要求分析程序输出当前仓库内最大集装箱的重量。

当仓库为空时你应该忽略出库操作,当仓库为空查询时你应该输出 00。

输出格式

输出行数等于日志中查询操作的次数。每行为一个整数,表示查询结果。

输入输出样例

输入 #1复制

13
0 1
0 2
2
0 4
0 2
2
1
2
1
1
2
1
2

输出 #1复制

2
4
4
1
0

说明/提示

数据范围及约定

  • 对于 20%20% 的数据,有N≤10;
  • 对于 40%40% 的数据,有 N≤1000;
  • 对于 100%100% 的数据,有 1≤N≤200000,1≤X≤108。

 题目分析

根据题意得出有几个注意点

1.用栈来写这个题目得用俩个栈一个是主栈用来存放箱子质量,辅助栈用来存放最大质量

2.考虑当仓库为空时应该忽略出库操作,当仓库为空查询时你应该输出 0。

3.当入库时的数据大于最大质量栈的栈顶,直接入栈,小于的话,原最大质量栈的栈顶不变

4每次为2时查询,其实都是在查询最大质量栈的栈顶

代码示例

#include
using namespace std;
stacks;
stacks1;
int n,p,mx;
int k;
int main()
{

    cin>>n;
    for(int i=0; i>k;
        if(k==0)
        {
            cin>>p;
            s.push(p);//入栈相当于装箱,其实更重要的是最大质量栈
            if(s1.empty()||p>s1.top())s1.push(p);//当入库时的数据大于最大质量栈的栈顶,直接入栈,小于的话,原最大质量栈的栈顶不变
            else s1.push(s1.top());//相当于没变
        }
        else if(k==1)
        {
            s.pop();//出栈,搬箱子
            s1.pop();//s1也要出栈的原因是他们俩个栈是对应关系,s的每次入栈都会把他入栈后的所得到的最大质量存放在s1栈里
        }
        else if(k==2)
        {
            if(s.empty())cout<<0<

有不足之处还望大佬指出

你可能感兴趣的:(学习,算法,数据结构,c++)