T1 .P4387 【深基15.习9】验证栈序列
需要思考的问题
1.如何储存输入的数据(数组还是直接输入)
2.怎么判断出栈序列和输入序列的差别(一个一个比)
3.栈的善后工作(清空栈,不知道为什么这个好像设了一个数据点)
解题思路
1.开两个数组,分别储存进栈数据和可能的出栈顺序
2.把储存进栈数组的元素压入栈
3.依次判断栈顶元素是否与给定输入元素相同,若相同则把该元素pop出来,并开始下一个数据的比较,若不同则不操作(实际上个人感觉只要有一个不同的就是错误输入把)
4.当操作完最后一个元素后如果栈中没有元素说明给定序列就是出栈序列
代码如下
//ac代码
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
stack<int>q;
int p,n;
int a[N],b[N];//a为入栈序列,b为出栈序列
int main()
{
scanf("%d",&p);
while(p--)
{
scanf("%d",&n);
int cnt=1;//计数器
for(int i=1;i<=n;i++)scanf("%d",&a[i]);//初始化数据
for(int i=1;i<=n;i++)scanf("%d",&b[i]);//
for(int i=1;i<=n;i++)
{
q.push(a[i]);//入栈
while((q.top())==b[cnt]) //当栈顶元素与b中当前元素相同时出栈
{
q.pop();//出栈
cnt++;//cnt++到b下一个元素
if(q.empty())break;//结束循环(不然会RE)
}
}
if(q.empty()) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
while(!q.empty())q.pop();
}
return 0;
}
//一开始写的(全部wa但不知道哪里错了😭)
#include<bits/stdc++.h>
using namespace std;
stack <int>s;
int main()
{
int n;
char x;
cin>>n;
for(int i=0;i<n;i++)
{
int t=1;
int m;//输入每组数据个数
cin>>m;
for(int k=0;k<m;k++)//入栈
{
int pu;
cin>>pu;
s.push(pu);
}
for(int k=0;k<m;k++)//判断是否是出栈序列
{
int po;
cin>>po;
if(po==s.top())s.pop();
else t=0;
}
if(t==0)cout<<"No"<<endl;
if(t==1)cout<<"Yes"<<endl;
}
}
T2.P3613 【深基15.例2】寄包柜
需要思考的地方
1.怎么存放数据(因为每个衣柜还有多个参数要储存所以用结构体数组)
2.怎么表示在给定位置放入东西(push back函数)
3.如果同个地方放多次那么要以最后一次为准
思路
1.建一个结构体数组,每个数组元素包括哪个格子和存了多少东西
2.输入数据,判断是存还是查
3.如果是存的话就把数据push_back到对应数组里,如果是查的话就输出这个位置最后一次是储存的数量
代码
#include<bits/stdc++.h>
using namespace std;
const int m=1e5+5;
struct block
{
int times;//表示存了几次
vector<int> num;//某个柜子的格子数
vector<int> good;//第num号柜子存放物品数目
}a[m];
int main()
{
int n,q;
cin>>n>>q;//其实感觉这里的n没什么用
while(q--)
{
int type;
cin>>type;
if(type==1)//放东西
{
int i,j,k;
cin>>i>>j>>k;
a[i].times++;
a[i].num.push_back(j);//把j放到num里最后一位(就是说最后容器可能有多个数)
a[i].good.push_back(k);//同上
}
else//查找
{
int b,c;
cin>>b>>c;
for(int i=a[b].times-1;i>=0;i--)//找最后一次放置的位置
{
if(a[b].num[i]==c)
{
cout<<a[b].good[i]<<endl;//输出对应位置存放的数量
break;
}
}
}
}
}
T3.P1449 后缀表达式
需要思考的地方
1.题目啥意思()
2.当你终于看明白题目后,那么怎么储存数据呢(栈)
3.怎么实现四则运算(先把栈顶push出来跟下一位运算)
4.题目中每个符号对应什么操作(当时我就不知道这个'.'究竟想让我干啥)
5.最后要输出的元素位置(一定是栈顶)
思路
1.创建一个栈来解决问题
2.遇到‘ . ’ 的时候把这之前的数转化成十进制
3.遇到其他运算符号把他前面两个数拿来做相应运算,具体方法是先把栈顶元素拿出来,再用top找到新栈顶,两者运算后在push到栈里面
4.输出栈顶
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ans=0;
stack<int>s;//用栈来解决这个问题
string str;
cin>>str;
for(int i=0;i!='@';i++)
{
int num=0;
int weight=1;//存放位权
if(str[i]=='.')//遇到这个符号就把前面的字符型数字转化为整型数字
{
for(int j=i-1;str[j]>='0'&&str[j]<='9';j--)//注意第二个语句是循环终止条件
{
num+=(str[j]-'0')*weight;
weight*=10;
}
s.push(num);//转换后数入栈
}
else if(str[i]>='0'&&str[i]<='9')continue;//如果是数字则跳过
else//遇到其他的运算符号
{
int f=s.top();//先把栈顶的数拿出来用来和下一个数做运算
s.pop();//栈顶出栈
if(str[i]=='+')//以下是四则运算
{
ans=s.top()+f;
s.pop();//使用完这个数就让他出栈
}
else if(str[i]=='-')
{
ans=s.top()-f;
s.pop();
}
else if(str[i]=='*')
{
ans=s.top()*f;
s.pop();
}
else if(str[i]=='/')
{
ans=s.top()/f;
s.pop();
}
s.push(ans);//把运算之后的结果加到栈里
}
}
cout<<s.top();//只需要输出栈顶(最后肯定只剩一个数)
}
T4.P1241 括号序列
需要思考的地方
1.还是看懂题目(感觉这种类型的题目读起来比较费劲)
2.怎么存数据(数组)
3.对于一个右括号如果找到最近左括号之后要干什么,配对失败具体要怎么转化为代码(设标识符,按情况置为0或1)
4.怎么输出处理之后的符号
思路
1.开两个数组,一个用来存数据,一个用来存标识符,初始化为1
2.遍历数据,对于发现的右括号找到理他最近的左括号,如果不是对应形式标识符置为0
3.对于标识符为1的元素照常输出,标识符为0的补上对应标识符后输出
代码
#include<bits/stdc++.h>
using namespace std;
string str;
int match[110];//用于存放标记是否匹配成功
int main()
{
cin>>str;
for(int i=0;i<str.size();i++)
{
if(str[i]==')')
{
for(int j=i-1;j>=0;j--)
if(!match[j]&&(str[j]=='['||str[j]=='('))//找到最近的左括号
{
if(str[j]=='('){//匹配的话就把标记置为1
match[i]=1;
match[j]=1;
}
break;
}
}
else if(str[i]==']')
{
for(int j=i-1;j>=0;j--)
if(!match[j]&&(str[j]=='['||str[j]=='('))//找到最近的左括号
{
if(str[j]=='['){//匹配的话就把标记置为1
match[i]=1;
match[j]=1;
}
break;
}
}
}
for(int i=0;i<str.size();i++)
if (match[i])cout<<str[i];//如果有匹配的元素就原样输出
else if(str[i]=='(')cout<<str[i]<<')';//如果没有匹配的括号就给加上
else if(str[i]==')')cout<<'('<<str[i];
else if(str[i]=='[')cout<<str[i]<<']';
else if(str[i]==']')cout<<'['<<str[i];
return 0;
}
T4.P1160 队列安排
需要思考的地方
1.怎么表示同学之间的关系(结构体+类链表)
2.怎么初始化第一个同学
3.如何表示一个同学插入另一个同学这个操作
3.怎么输出数据
思路
1.创建一个结构体数组,每个元素都有左手和右手两种形态
2.创造出第零个同学用来初始化(神奇)
3.进行插入操作,具体地说比如插在左边就把这个同学的左手连上这个同学右边的人的右手,再对这个同学附近的人的左右手作变换
4.输出每个同学的右手(实际上每个人的右手就代表下一个人,0同学的右手实际上是1同学,而且最后输出的时候不输出最后一个同学的右手)
代码
#include<bits/stdc++.h>
using namespace std;
const int mx=1e5+10;
struct T
{
int l,r;
}arr[mx]={0};
void add(int x,int y,int p)//把y同学插到x同学p位置
{
if(p==1)//插到右边
{
arr[y].r=arr[x].r;
arr[y].l=x;
arr[x].r=y;
arr[arr[y].r].l=y;//实际上这里的arr[y].r就是原来的arr[x].r
//意思就是原来x右边的现在变成y右边的同学
}
else//插到左边
{
arr[y].r=x;
arr[y].l=arr[x].l;
arr[x].l=y;
arr[arr[y].l].r=y;//同上
}
}
void del(int x)//删除第x个人
{
if(arr[x].r==0&&arr[x].l==0)//如果之前删除过就跳过
return;
arr[arr[x].l].r=arr[x].r;//被删的右边现在变成被删的同学左边的同学的右边
arr[arr[x].r].l=arr[x].l;//同上
arr[x].l=arr[x].r=0;//清空该同学信息,相当于把他和其他节点链接的信息切断
}
int main()
{
int n;
int x,y,p;//把y加到x的p位置
cin>>n;
arr[0].r=0,arr[0].l=0;//
add(0,1,1);//新定义起始点用来初始化
for(int i=2;i<=n;i++)//因为0.1都被定义好了所以循环要从第三个(实际上是第二个)同学开始
{
cin>>x>>p;
add(x,i,p);
}
int out;//输入要删除元素的个数
cin>>out;
for(int i=0;i<out;i++)//删除元素
{
int pos;
cin>>pos;
del(pos);
}
for (int i=arr[0].r;i;i=arr[i].r)//打印(注意循环的条件写法[妙啊])
cout<<i<<' ';
}