建议多看standing榜首几个大佬的代码,思路清晰也写的简洁。
题意:给一个由A,B,C组成的字符串,用 ‘(’ 或者 ‘)’ 替换其中一种字母,要求相同字符替换后也必须相同,判断是否存在一种方案,使得替换后的括号串,符合日常运算写法的形式。
思路1:第一个字母必然时左括号,最后一个字母必然是右括号,剩下一个字母就只剩两种情况,枚举剩下字母的状态,再判断序列是否合法就行。
但个人更加推荐第二种思路,虽然程序计算量更大,但简单粗暴,对付水题这种方法思路更加简单,时间也够,也不用担心自己思路出错。
思路2:二进制枚举
ABC每个字符只有两种被替换后的状态,于是所有的情况就是
2
∗
2
∗
2
=
8
2*2*2=8
2∗2∗2=8种,二进制枚举所有状态即可。
思路2代码:
#include <bits/stdc++.h>
using namespace std;
bool check(string s1){
int blance=0;
for(auto c :s1){
if(c=='(')blance++;
else blance--;
if(blance<0) return 0;
}
if(blance)return 0;
return 1;
}
void solve(){
string s;
cin>>s;
for(int mask=0;mask<8;mask++){//mask意为掩膜,代表分割后的结果
string s1;
for(auto c :s){//推荐这样遍历字符串,省手写时间
if(mask&1<<(c-'A'))s1+='(';//注意位移运算优先级大于位运算
else s1+=')';
}
if(check(s1)){
cout<<"YES\n";
return;
}
}
cout<<"NO\n";
}
int main(){
int T;
cin>>T;
while(T--){
solve();
}
}
题意:有一个由 n ∗ n n*n n∗n的白色方块组成的矩阵,给出分别给出n,上,右,下,左边所需要涂黑的方块个数,判断是否能够完成涂色。
思路:判断涂色任务是否能够完成的关键,在于矩形四角是否涂色,每个角仅有两种状态,涂色和不涂色,总共 2 4 2^4 24种状态,二进制枚举即可。涂黑的角就在对应两邻边要求数量的基础上减去1即可。
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n,U,R,D,L,u,r,d,l;
cin>>n>>U>>R>>D>>L;
bool f=0;
for(int mask=0;mask<16;mask++){
u=r=d=l=0;
if(mask&1)u++,r++;
if(mask&2)r++,d++;
if(mask&4)d++,l++;
if(mask&8)l++,u++;
if(u>U||U-u>n-2)continue;
if(r>R||R-r>n-2)continue;
if(d>D||D-d>n-2)continue;
if(l>L||L-l>n-2)continue;
f=1;
}
if(f)cout<<"YES\n";
else cout<<"NO\n";
}
int main(){
int T;
cin>>T;
while(T--){
solve();
}
}
题意:1维推箱子游戏,不能穿过拉扯箱子,推的当前的箱子如果挨到后面的箱子,可以连着一起推,求最多能把多少箱子推到指定位置上。
思路:正负两边对称,于是只算一种情况的解法,两边结果相加就行,然后模拟推箱子的情况,计算答案,用lower_bounder,搜索下一个点的位置,避免超时。
#include<bits/stdc++.h>
#include<vector>
#include<set>
using namespace std;
int calc(vector<int> a,vector<int> b){
int n=a.size(),m=b.size();
vector<int>suf(n+1,0);
set<int>pos( b.begin() , b.end() );
for(int i=n-1;i>=0;i--){
suf[i]=suf[i+1];
if( pos.count(a[i]) )suf[i]++;
}//suf[i]表示推动第i个箱子时,在正确位置上的数量。
int ans=suf[0];//一个都不动的时候
for(int take=1;take<=n;take++){ //take表示第take-1个箱子堆积的长度
auto it=lower_bound( b.begin(), b.end() ,a[take-1]);
if (it==b.end()) continue;
int idx= it - b.begin();
int LIM= 1e9+5;
if(take<n)LIM =a[take]-1;
while(idx<m&&b[idx]<=LIM){//将长度为take的箱子,推到take+1的位置前的b处。
int idx1=lower_bound(b.begin(), b.end() ,b[idx]-take+1 )-b.begin();
ans=max(ans,suf[take]+idx-idx1+1);
idx++;
}
}
return ans;
}
void solve(){
int n,m,ans=0;
cin>>n>>m;
vector<int>a(n),b(m),a1,b1;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<m;i++)cin>>b[i];
for(auto it:a)if(it>0) a1.push_back(it);
for(auto it:b)if(it>0) b1.push_back(it);
ans+=calc(a1,b1);
a1.clear();b1.clear();
for(auto it:a)if(it<0) a1.push_back(-it);
for(auto it:b)if(it<0) b1.push_back(-it);
reverse(a1.begin(),a1.end());
reverse(b1.begin(),b1.end());
ans+=calc(a1,b1);
cout<< ans << endl;
}
int main(){
ios_base::sync_with_stdio(0);//cin记得关闭同步流不然会浪费很多额外时间
cin.tie(nullptr);
int t;
cin>>t;
while(t--){
solve();
}
}
因篇幅问题不能全部显示,请点此查看更多更全内容