A. 字符画
暴力
大概思路
倒着扫描一遍整个图就可以排除遇到假8,假P,假F的可能了
参考代码
string P[6],B[6],F[6];
string s[505];
int cP,cB,cF;
void EX(int cx,int cy){//擦除已匹配图块
FOR(i,cy-2,cy+2){
s[i]=(s[i].substr(0,cx-1)+"...")+s[i].substr(cx+1+1);
}
}
bool ck(char c,int cy,int cx){//检查是否为某个图块
if(c=='B'){
FOR(i,cy-2,cy+2){
if(s[i].substr(cx-1,3)!=B[i-(cy-2)+1])return 0;
}
cB++;
EX(cx,cy);
return 1;
}else if(c=='P'){
FOR(i,cy-2,cy+2){
if(s[i].substr(cx-1,3)!=P[i-(cy-2)+1])return 0;
}
cP++;
EX(cx,cy);
return 1;
}else{
FOR(i,cy-2,cy+2){
if(s[i].substr(cx-1,3)!=F[i-(cy-2)+1])return 0;
}
cF++;
EX(cx,cy);
return 1;
}
}
void solve(){
B[1]="###";
B[2]="#.#";
B[3]="###";
B[4]="#.#";
B[5]="###";
P[1]="###";
P[2]="#.#";
P[3]="###";
P[4]="#..";
P[5]="#..";
F[1]="###";
F[2]="..#";
F[3]=".##";
F[4]="..#";
F[5]="..#";
CIN(n);CIN(m);
FOR(i,1,n){cin>>s[i];s[i]=" "+s[i];}
rFOR(i,n-2,1+2)FOR(j,1+1,m-1){//倒序遍历整个图
for(auto c:{'B','P','F'}){
if(ck(c,i,j))break;
}
}
cout<<cP<<" "<<cF<<" "<<cB;
}
G. 能赢吗?会赢的!
二分。(思路非常快的一题,第一次抢到线下赛首AC)
大概思路
一眼二分,ck函数按照题意模拟即可。
参考代码
void solve(){
CIN(n);vector<int> a(n+1,0),h(n+1,0);
FOR(i,1,n){cin>>a[i];h[i]=a[i]+(a[i-1]+1)/2;}//读入“基础生命值”后预处理“真实生命值”(其实没必要,在ck函数里把h[i]换成a[i]+(a[i-1]+1)/2也行,这里预处理只是略微降低了一下常数(加减乘除的常数有降低的必要嘛))
auto ck=[&](ll x){//二分ck函数,按题意模拟即可
FOR(i,1,n){
if(x>h[i]){
x+=a[i]/2;
}else{
return 0;
}
}
return 1;
};
ll l=0,r=1e18;
while(l<=r){//二分板子,注意边界
ll mid=(l+r)/2;
if(ck(mid))r=mid-1;
else l=mid+1;
}
cout<<r+1;//这里要注意,一般是看你ck(mid)成功后,靠r/l更新的式子反推回去
}
H. NING-NING-chatgpt
水题,map
大概思路
直接map映射即可(赛时还把映射写反了,一个个对换回去。。)
参考代码
void solve(){
map<char,char> mp;
FOR(i,'a','z')mp[i]=i;
mp['4']='a';mp['6']='b';
mp['3']='e';mp['9']='g';
mp['1']='l';mp['0']='o';
mp['5']='s';mp['7']='t';
mp['2']='z';mp[' ']=' ';
string s;getline(cin,s);//有强调空格的题一律用getline
for(auto c:s)cout<<mp[c];
}
J. 矩阵最大路径与
位运算,数位DP,BFS
大概思路
按数位倒着跑BFS,逐个确定ans的各个数位的最优状态
参考代码
void solve(){
CIN(n);CIN(m);
vector<vector<int>> a(n+1,vector<int>(m+1));
vector<vector<int>> vis(n+1,vector<int>(m+1));
FOR(i,1,n)FOR(j,1,m)cin>>a[i][j];
ll ans=0;
rFOR(k,29,0){
FOR(i,1,n)FOR(j,1,m)vis[i][j]=0;
ans|=(1<<k);//设当前位为1,试试跑到最后能不能保留这位
queue<pair<int,int>> q;
if(((a[1][1]&ans)==ans)&&((a[n][m]&ans)==ans)){
q.push({1,1});
vis[1][1];
}
int dx[]={0,0,1,-1};//一种很新的四方向遍历写法
int dy[]={1,-1,0,0};
while(q.size()){
auto t=q.front();q.pop();
auto &[x,y]=t;
FOR(i,0,3){
int tx=x+dx[i];
int ty=y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&(vis[tx][ty]==0)){
if((a[tx][ty]&ans)==ans){
vis[tx][ty]=1;
q.push({tx,ty});
}else{
vis[tx][ty]=2;//vis设置成不为0就行,代表已经走过了
}
}
}
}
if(vis[n][m]!=1)ans^=(1<<k);//如果没法保留,那么撤销这位的置1
}
cout<<ans;
}
K. gzhu is all you need!
模拟
大致思路
按题意跑模拟即可
参考代码
void solve(){
CIN(n);string s;cin>>s;
map<char,int> mp;
ll power=0,cost=0;
for(auto c:s){
if(power)power--;
else{
cost++;
mp[c]++;
if(mp['g']&&mp['z']&&mp['h']&&mp['u']){
power+=mp['g']+mp['z']+mp['h']+mp['u'];
mp['g']=mp['z']=mp['h']=mp['u']=0;
}
}
}
cout<<cost;
}
M. 计算几何
排序
大概思路
根本就不是计算几何,是线段相交而不是直线相交,直接按点排序,一个个连过去即可
参考代码
void solve(){
CIN(n);
vector<tuple<int,int,int>> a;
FOR(i,1,n){
CIN(x);CIN(y);
a.push_back({x,y,i});
}
sort(a.begin(),a.end());
cout<<n/2<<ET;
FOR(i,0,(n>>1<<1)-1){
cout<<get<2>(a[i])<<" \n"[i%2];
}
}
附录
这里贴上用到的头部和main函数:
#include<iostream>
#include<vector>
#include<cmath>
#include<set>
#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
#define ET '\n'
#define FOR(i,a,b) for(ll i=(a);i<=(b);i++)
#define rFOR(i,a,b) for(ll i=(a);i>=(b);i--)
//趋向for循环,一般情况别用,规定方向时会跳出的循环在这里不会跳出
#define rep(i,a,b) for(ll i=(a);i!=(b)+2*(a<b)-1;i+=2*(a<b)-1)
#define CIN(a) ll a;cin>>a
#define DCIN(a) ld a;cin>>a
#define SCIN(a) string a;cin>>a
#define CA cout<<ans<<ET
#define CY cout<<"YES"<<ET
#define CN cout<<"NO"<<ET
#define max(a,b) ((a>b)?(a):(b))
#define min(a,b) ((a<b)?(a):(b))
std::mt19937 myrand(time(0));
ll rnd(ll l, ll r) {return std::uniform_int_distribution<ll>(l, r)(myrand);}
//没有C++20就不能用ranges了//CF又可以用C++20了,封印解除
#define PP(l,r,CK) *ranges::partition_point(ranges::iota_view((l),(r)+1),(CK))
int M=1e9+7;
inline ll MO(ll x){return (x%M+M)%M;}
string ANS[2]={"No\n","Yes\n"};
void solve(){
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//pre();
//CIN(t);while(t--)
solve();
return 0;
}