Educational Codeforces Round 105 (Rated for Div. 2)
A. ABC String
枚举ABC分别为“( ”和 “ )”的情况,然后判断是否为合法字符串。
map<char,int> book;
string tt="()";
string s;
bool judge(string ss)
{
int num=0;
for(int i=0;i<ss.length();i++)
{
if(ss[i]=='(') num++;
else num--;
if(num<0) return false;
}
if(num==0) return true;
return false;
}
bool solve()
{
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
string tmp="";
for(int l=0;l<s.length();l++)
{
if(s[l]=='A') tmp+=tt[i];
else if(s[l]=='B') tmp+=tt[j];
else tmp+=tt[k];
}
if(judge(tmp)) return true;
}
return false;
}
int main()
{
ios;
int t;
cin >> t;
while (t--) {
book.clear();
cin >> s;
if(solve()) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
B. Berland Crossword
暴力枚举四个角是否为黑色,共16种情况,找到符合条件的退出。
bool s1=false,s2=false,s3=false,s4=false;
void f(int p)
{
int num=p;
string s="";
while (num) {
if(num%2) s+='1';
else s+='0';
num/=2;
}
int n=s.length();
for(int i=0;i<4-n;i++) s=s+='0';
for(int i=0;i<4;i++)
{
if(s[0]=='1') s1=true;
if(s[1]=='1') s2=true;
if(s[2]=='1') s3=true;
if(s[3]=='1') s4=true;
}
}
int main()
{
ios;
int t;
cin >> t;
while (t--) {
int n,u,r,d,l;
cin >> n >> u >> r >> d >> l;
int u1=0,r1=0,d1=0,l1=0;
bool flag=false;
for(int i=0;i<16;i++)
{
u1=0,r1=0,d1=0,l1=0;
s1=false,s2=false,s3=false,s4=false;
f(i);
if(s1) { u1++,l1++; }
if(s2) { u1++,r1++; }
if(s3) { r1++,d1++; }
if(s4) { d1++,l1++; }
if((u-u1)<n-1 && (l-l1)<n-1 && (d-d1)<n-1 && (r-r1<n-1) && u1<=u && l1<=l && d1<=d && r1<=r)
{ cout << "YES" << endl; flag=true;break;}
}
if(!flag) cout << "NO" << endl;
}
}
C. 1D Sokoban
坐标正数和负数推箱子的情况是一样的,只需考虑一边即可。本题就是模拟将箱子朝一边推,箱子第一次到达每个目标点时,计算箱子覆盖目标点的个数,取最大值即可。
int a[maxn],b[maxn];
map<int,int> book;
int n,m;
vector<int> as,bs;
int f()
{
book.clear();
for(int i=0;i<as.size();i++) book[as[i]]=1;
int sum=0;
for(int i=0;i<bs.size();i++)
{
if(book[bs[i]]==1) sum++;
}
int ans=sum;
for(int i=0;i<bs.size();i++)
{
if(book[bs[i]])
{
sum--;
continue;
}
int num=upper_bound(as.begin(), as.end(), bs[i])-as.begin(); //bs[i]之前有多少个箱子
int pos=lower_bound(bs.begin(), bs.end(),bs[i]-num+1)-bs.begin();
//推的箱子刚好接触bs[i]时,之前的箱子有多少个在规定坐标上
ans=max(ans,sum+i-pos+1);
}
return ans;
}
int main()
{
ios;
int t;
cin >> t;
while (t--) {
cin >> n >> m;
int ans=0;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=m;i++) cin >> b[i];
as.clear(),bs.clear();
for(int i=1;i<=n;i++)
{
if(a[i]>0) as.pb(a[i]);
}
for(int i=1;i<=m;i++)
{
if(b[i]>0) bs.push_back(b[i]);
}
ans+=f();
as.clear(),bs.clear();
for(int i=n;i>=1;i--)
{
if(a[i]<0) as.push_back(-a[i]);
}
for(int i=m;i>=1;i--)
{
if(b[i]<0) bs.push_back(-b[i]);
}
ans+=f();
cout << ans << endl;
}
}