第一题:
小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为m|S(m为一个整数且1<=m<=100),例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?
思路:这里直接dfs栈模拟即可
#include<bits/stdc++.h>
using namespace std;
string strr;
int len=0;//字符串长度
int pos = 1;//遍历到字符串的位置
string dfs(){
string s="";
if(pos==len) return s;
int number = 0;
string ss="";
while(pos<len){
if(strr[pos]=='['){
++pos;
ss+=dfs();
}
//数字的处理
else if(strr[pos]>='0'&&strr[pos]<='9'){
while(strr[pos]!='|'&&pos<len){
number = number*10+(strr[pos]-'0');
pos++;
}
pos++;
}
//字母
else if(strr[pos]>='A'&&strr[pos]<='Z'){
ss+=strr[pos];
pos++;
}
else if(strr[pos]==']'){
s=ss;
while(--number){
s+=ss;
}
pos++;
return s;
}
}
return ss;
}
int main(){
cin>>strr;
len = strr.length()-1;
cout<<dfs();
}
第二题:
小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。
小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)
思路:从前往后和从后往前遍历数组,分别维护两个单调递减栈表示站在当前位置向前和向后能看到的房子个数,最后再加上1(当前脚下的房子不要忘记算)
#include<bits/stdc++.h>
using namespace std;
stack<int>s;
const int Maxn = 1e6+10;
int Left[Maxn];
int Right[Maxn];
int a[Maxn];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
//向前能看到的房子个数
Left[i] = s.size();
while(!s.empty()&&s.top()<=a[i]){
s.pop();
}
s.push(a[i]);
}
while(!s.empty()) s.pop();
for(int i=n;i>=1;i--){
//向后能看到的房子个数
Right[i] = s.size();
while(!s.empty()&&s.top()<=a[i]){
s.pop();
}
s.push(a[i]);
}
for(int i=1;i<=n;i++){
cout<<Left[i]+Right[i]+1<<' ';
}
return 0;
}
第四题:
由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。
思路:简单dp一下即可,dp思路,dp[i][0]表示前i天,第i天选择休息的休息天数,dp[i][1]表示前i天,第i天选择工作的休息天数,dp[i][1]表示前i天,第i天选择健身的休息天数,最后取min(dp[n][0],dp[n][1],dp[n][2])即可
#include<bits/stdc++.h>
using namespace std;
const int Maxn = 1e6+10;
const int INF = 1e9;
int a[Maxn],b[Maxn];
int dp[Maxn][3];//0休息,1工作,2健身
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
}
dp[0][0] = 0;
dp[0][1] = 0;
dp[0][2] = 0;
for(int i=1;i<=n;i++){
//今天可以工作
if(a[i]){
dp[i][1] = min(dp[i-1][0],dp[i-1][2]);
}
//今天不可以工作
else dp[i][1] = INF;
//今天可以健身
if(b[i]){
dp[i][2] = min(dp[i-1][0],dp[i-1][1]);
}
//今天不可以健身
else dp[i][2] = INF;
dp[i][0] = min(dp[i-1][1],min(dp[i-1][0],dp[i-1][2]))+1;
}
cout<<min(dp[n][0],min(dp[n][1],dp[n][2]))<<'\n';
return 0;
}
第五题:
由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。
思路:首先把输入数据放在结构体,然后按照x从小到大排序,x相同的按照y从小到大排序,然后去不断更新覆盖区域中守卫延申最远的右端点,就这样不断延申,看看需要多少个守卫即可
#include<bits/stdc++.h>
using namespace std;
const int Maxn = 1e5+10;
typedef struct node{
int x,y;
}Node;
Node stu[Maxn];
int cmp(Node a,Node b){
if(a.x==b.x) return a.y>b.y;
return a.x<b.x;
}
int main(){
ios::sync_with_stdio(false);
int n,L;
cin>>n>>L;
for(int i=1;i<=n;i++){
cin>>stu[i].x>>stu[i].y;
}
sort(stu+1,stu+n+1,cmp);
if(stu[1].x>0){
cout<<-1<<'\n';
return 0;
}
int now = stu[1].y,Max = stu[1].y;
int cnt = 1;
for(int i=1;i<=n+1;i++){
if(now>=L) break;
if(stu[i].x<=now){
Max = max(Max,stu[i].y);
if(Max>=L){
now = Max;
cnt++;
break;
}
}
else{
cnt++;
now = Max;
i--;
}
}
// cout<<now<<'\n';
if(now>=L)
cout<<cnt<<'\n';
else cout<<-1<<'\n';
return 0;
}