计蒜客 2020 蓝桥杯大学 B 组省赛模拟赛(一)(部分题解)

写在前面:

这一套题真是做了一晚上只对了仨填空- - 其中一个还是靠记得小学数学一道题 蒙上的答案 还对了。。。
要是蓝桥还这个难度我就完辽。。。自己真的太菜辽。。。
qxgg说 不要轻视蓝桥 它简单的题贼简单 难的题贼难 而且是oi赛制 所以如果遇到大题不会了 也要输出样例骗分
因为蓝桥和ACM不一样 不能得到自己代码的实时反馈结果 所以一定要求稳!各种小错误一有就完了!!!

目录:

A.填空:有趣的数字

没什么说的直接暴力判断

const int maxn=1e5+10;
int prime[maxn];
bool con[maxn];
inline bool judge(int num){
    while(num){
        if(num%10==5) return true;
        num/=10;
    }
    return false;
}
int main() {
	rep(i,2,maxn-1){
        if(con[i]) continue;
        rep(j,2,maxn){
            if(i*j>=maxn) break;
            con[i*j]=true;
        }
    }
    int k=0;
    rep(i,2,maxn-1){
        if(!con[i]) prime[++k]=i;
    }
    int cnt=0;
    rep(i,1,k){
        if(prime[i]>100000) break;
        if(judge(prime[i])) cnt++;
    }
    printf("%d\n",cnt);
	return 0;
}

B.填空:爬楼梯

一共才十层 搜索一下就好

int dfs(int d){
    if(d==1) return 1;
    if(d==2) return 2;
    if(d==3) return 1+dfs(2)+dfs(1);
    if(d==4) return 1+dfs(3)+dfs(2)+dfs(1);
    if(d==5) return 0;
    if(d==7) return 0;
    return dfs(d-1)+dfs(d-2)+dfs(d-3)+dfs(d-4);
}
int main() {
	printf("%d\n",dfs(10));
    system("pause");
	return 0;
}

C.填空:七巧板

这个我是想起小学的切饼问题。。。
总之每一条直线(每一刀
都切中尽可能多的块就行
第一次发现可以切6块 所以会多六块 然后后面每次切就多一块
所以答案=7+6+7+8+9+10=47
没想到竟然对了。。。没写代码。。。直接这么想的

D.填空:苹果

自己不会。。题解说从左往右 先拿一堆三个的 再拿三堆 一堆一个的拿
小贪心吧
下面是代码

//从两个方向贪心 优先一堆拿三个 不够了再从右边
int a[33],b[33];
int main() {
    rep(i,1,30){
        sd(a[i]);
        b[30+1-i]=a[i];
    }
    int cnt=0,cnt2=0;
	for(int i=1;i<=30;i++){
        cnt+=a[i]/3;
        a[i]%=3;
        while(a[i]>=1&&a[i+1]>=1&&a[i+2]>=1){
            a[i]--,a[i+1]--,a[i+2]--;
            cnt++;
        }
        cnt2+=b[i]/3;
        b[i]%=3;
        while(b[i]>=1&&b[i+1]>=1&&b[i+2]>=1){
            b[i]--,b[i+1]--,b[i+2]--;
            cnt2++;
        }
    }
    rep(i,1,30) printf("%d ",a[i]);putchar('\n');
    rep(i,1,30) printf("%d ",b[i]);putchar('\n');
    printf("%d %d\n",cnt,cnt2);
    printf("%d\n",max(cnt,cnt2));
	return 0;
}

E.填空:方阵

和欧拉函数有点关系 会补的 算了就这样吧 太难了太难了

F.寻找重复项

题解用了unordered_map 不会用啊莫名其妙的 会补的 补是不可能的

G.被袭击的村庄

写到吐的大模拟
昨天晚上没过 今天早晨起来一搜题解说 题面错了
应该统计三种各自有多少被降低为0 而不是各自受的伤害
然后改了之后还是不对
发现自己计算溅射伤害方法有问题 因为遇到边界 某一点受到的溅射伤害可能不是3 5 8 而且还要分析k*k 之外收到的溅射伤害- -这里忘了
然后改了之后发现还是不对
发现最后总数可能爆int 最后改了long long 就对了- -

const int maxn=310;
ll blood[4];//三种血量
ll sum[4];//三种受的伤
int mp[maxn][maxn];//编号地图
ll now[maxn][maxn];//血量地图
ll hurt[maxn][maxn];//基本伤害
ll jian[maxn][maxn];//溅射伤害 事实证明用不到- -
int dir[8][2]={1,0,1,1,0,1,-1,1,-1,0,-1,-1,0,-1,1,-1};
int main() {
    int n,m;
    sdd(n,m);
    scanf("%lld%lld%lld",&blood[1],&blood[2],&blood[3]);
    int k;
    ll w;//范围与溅射伤害
    scanf("%d%lld",&k,&w);
    rep(i,1,k){
        rep(j,1,k){
            scanf("%lld",&hurt[i][j]);
        }
    }
    rep(i,1,n)
        rep(j,1,m){
            sd(mp[i][j]);
            now[i][j]=blood[mp[i][j]];
        }
    //计算攻击
    int q;
    sd(q);
    while(q--){
        int op,x,y;
        sd(op);sdd(x,y);//爆炸中心x y
        //先基本伤害 默认k是奇数
        int s1,s2,t1,t2;//行列开始 行列结束
        s1=max(1,x-k/2);
        t1=min(n,x+k/2);
        s2=max(1,y-k/2);
        t2=min(m,y+k/2);
        rep(i,s1,t1){
            rep(j,s2,t2){
                //ii jj是对应炸弹范围的坐标
                //1 1 
                int ii=i-(x-k/2-1);
                int jj=j-(y-k/2-1);
                if(now[i][j]>0){//若当前土地还有
                    sum[mp[i][j]]+=min(now[i][j],hurt[ii][jj]);
                    now[i][j]-=hurt[ii][jj];
                }
                if(op==0){//若有溅射伤害
                    //得分情况算
                    for(int dd=0;dd<8;dd++){//地图上的八个方向
                        int i1=i+dir[dd][0];
                        int j1=j+dir[dd][1];
                        if(i1<1||i1>n||j1<1||j1>m) continue;
                        if(now[i1][j1]>0){
                            sum[mp[i1][j1]]+=min(now[i1][j1],w);
                            now[i1][j1]-=w;
                        }
                    }
                }
            }
        }
    }
    int cnt[4]={0,0,0,0};
    rep(i,1,n)
        rep(j,1,m)
            if(now[i][j]<=0) cnt[mp[i][j]]++;
    //sum有可能超限!!!
    printf("%d %d %d\n%lld\n",cnt[1],cnt[2],cnt[3],sum[1]+sum[2]+sum[3]);
    //system("pause");
	return 0;
}

H.字符串

26进制转换 大数模拟balabla 自己大数计算从来不好 会补的 补是不可能的- -

I.最短路

题面有点问题 应该是n-1个顾客
之前做过这种类型的 因为求的是1到其他各点 和其他各点到1这个点的最短路
所以只用单源最短路即可 第二次反向建边 求和所有的dis即可
要注意!dis要初始化为1e18以上 !!自己刚开始不到这个 过的组数只有五组- -
下面是ac代码 (dijkstra+堆优化

const int maxn=2e4+10;
const int maxm=6e4+10;
int n,m,cnt;
ll ans;
struct Side0{
    int u,v;
    ll val;
}side0[maxm];
struct Side{
    int v,next;
    ll val;
}side[maxm];
int head[maxn],con[maxn];
ll dis[maxn];
struct node{
    int id;
    ll dis;
    bool operator<(const node &oth)const{
        return dis>oth.dis;
    }
};
void add(int u,int v,ll val){
    side[cnt].v=v;
    side[cnt].val=val;
    side[cnt].next=head[u];
    head[u]=cnt++;
}
void dijkstra(){
    priority_queue<node> q;
    while(!q.empty()) q.pop();
    rep(i,1,n) {//服了!!!就是这里!!!
        dis[i]=0x3f3f3f3f3f3f3f3f;//inf不够大!!!
        con[i]=0;
    }
    dis[1]=0;
    node tp;
    tp.id=1;
    tp.dis=0;
    q.push(tp);
    while(!q.empty()){
        int u=q.top().id;
        if(con[u]){
            q.pop();
            continue;
        }
        con[u]=1;
        for(int i=head[u];i!=-1;i=side[i].next){
            int v=side[i].v,val=side[i].val;
            if(dis[v]>dis[u]+val){
                dis[v]=dis[u]+val;
                tp.id=v,tp.dis=dis[v];
                q.push(tp);
            }
        }
    }
    rep(i,2,n) ans+=dis[i];
}
void fun1(){//正向建边求路
    cnt=0;
    rep(i,1,n) head[i]=-1;
    rep(i,1,m)
        add(side0[i].u,side0[i].v,side0[i].val);
    dijkstra();
}
void fun2(){//反向建边
    cnt=0;
    rep(i,1,n) head[i]=-1;
    rep(i,1,m){
        add(side0[i].v,side0[i].u,side0[i].val);
    }
    dijkstra();
}
int main() {
	int T;
    sd(T);
    while(T--){
        sdd(n,m);
        ans=0;
        rep(i,1,m){
            sdd(side0[i].u,side0[i].v);
            scanf("%lld",&side0[i].val);
        }
        fun2();
        fun1();
        printf("%lld\n",ans);
    }
	return 0;
}

J.迷宫

这个题要注意以下几点:
1、bfs很容易确定 因为是最少多少花费
2、对于当前的某个点 我们操作步骤是:1、该点是否为终点 2、该点是不是传送门起点 3、该点周围四个点能否到达
为什么要先判断是否为传送门起点而不是四周的点呢?
因为传送门花费为0 四周的点花费为1

const int maxn=1010;
int n,m,num,x,y;//传送门个数
char mp[maxn][maxn];//地图
bool con[maxn][maxn];//这个点有没有来过
int nextt[4][2]{1,0,0,1,-1,0,0,-1};
struct tran{
    int a,b,c,d;
}door[110];
struct node{
    int x,y,dep;//所花费时间
    bool operator<(const node &oth)const{
        return dep>oth.dep;
    }
};
bool inline judge(int x,int y){
    if(x<1||x>n||y<1||y>m||con[x][y]||mp[x][y]=='*') return false;
    return true;
}
int bfs(){
    queue<node> q;
    while(!q.empty()) q.pop();
    node tp;
    tp.x=tp.y=1;
    tp.dep=0;
    q.push(tp);
    con[1][1]=true;
    while(!q.empty()){
        //printf("%d %d %d\n",q.top().x,q.top().y,q.top().dep);
        tp=q.front();
        q.pop();
        bool flag=false;//先!!判断是否为传送门 是传送门的话 无法往周围走
        rep(i,1,m){//哈哈哈哈哈AC了哈哈哈哈哈哈!就是这个flag判断!!!
            if(tp.x==door[i].a&&tp.y==door[i].b){
                flag=true;
                if(!judge(door[i].c,door[i].d)) break;
                node tp1;
                tp1.x=door[i].c;
                tp1.y=door[i].d;
                tp1.dep=tp.dep;
                q.push(tp1);
                break;
            }
        }
        if(flag) continue;
        for(int i=0;i<4;i++){//除了四个方向外 还要有传送门的方向
            node tp1;
            tp1.x=tp.x+nextt[i][0];
            tp1.y=tp.y+nextt[i][1];
            tp1.dep=tp.dep+1;
            if(!judge(tp1.x,tp1.y)) continue;
            if(tp1.x==x&&tp1.y==y) return tp1.dep;
            q.push(tp1);
            con[tp1.x][tp1.y]=true;
        }
    }
    return -1;
}
int main() {
	sdd(n,m);getchar();
    rep(i,1,n){
        rep(j,1,m){
            con[i][j]=false;
            mp[i][j]=getchar();
        }getchar();
    }
    sd(num);
    rep(i,1,num){
        sdd(door[i].a,door[i].b);
        sdd(door[i].c,door[i].d);
    }
    sdd(x,y);
    int ans=bfs();
    if(ans==-1) printf("No solution\n");
    else printf("%d\n",ans);
    //system("pause");
	return 0;
}
发布了120 篇原创文章 · 获赞 12 · 访问量 5272

猜你喜欢

转载自blog.csdn.net/weixin_43735161/article/details/104728921