2016年蓝桥杯B组初赛(第七届)

写在前面的话,蓝桥杯快要开始了。毕竟参加了就得做些准备,今天开始做一些题目练习一下,为4月1号的比赛做些准备。
题目见:http://blog.csdn.net/Dodd9199/article/details/50936774

第一题:
简单的求和题。

#include<iostream>
#include<cmath>
using namespace std;
int a[110];

int main(){
    int i;
    int sum=0;
    a[1]=1;
    for(i=1;i<100;i++){
        a[i+1]=a[i]+i+1;
    }
    for(i=1;i<=100;i++){
        sum+=a[i];
    }
    cout<<sum<<endl;
    return 0;
}

第二题:
暴力,i,j分别代表起点和终点,遍历求解,简单题。
也可以利用等差数列求和公式,求出以i开头,j结尾等差数列的和。然后遍历i,j看能不能让sum恰好等于236

#include<iostream>
#include<cmath>
using namespace std;
int a[110];
int ans=0;
bool flag=false;

int main(){
    int i,j;
    for(i=1;i<=100;i++){
        ans=i;
        for(j=i+1;j<=100;j++){
            ans+=j;
            if(ans==236){
                flag=true;
                break;
            }
        }
        if(flag) break;
    }
    cout<<i<<endl;
    return 0;
}

第三题:
填数字问题,这里很巧妙的运用了C++中的next_permutation(a,a+n);生成1-9的全排列。(注意头文件#include<algorithm>
开始这道题目写错了,那个p,q是double类型,开始写成了int类型,所以一直是错的。以后注意类型问题。
还要注意的事情是,next_permutation生成全排列的时候注意要先给数组赋值。比如a={1,3,4,5};

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int a[11];
int ans=0;
void init(){
    int i;
    for(i=0;i<9;i++){
        a[i]=i+1;
    }
}

void Solve(){
    do{
        double p=1.0*a[1]/a[2];
        double q=1.0*(100*a[3]+10*a[4]+a[5])/(100*a[6]+10*a[7]+a[8]);
        if(a[0]+p+q==10){
            ans++;
        }
    }while(next_permutation(a,a+9));
}

int main(){
    init();
    Solve();
    cout<<ans<<endl;
    return 0;
}

第四题:程序填空-快速排序
刚刚学了快速排序算法的原理,算法思路就是:
先选定一个基数,通常选定第一个数就可以;
分别从左到右和从右到左遍历,从右向左遍历,使得左边的数都小于基数,右边的数都大于基数;再把基数查到对应的位置
这样一个数组就分成两端,重复。
这篇博客讲的非常好:
http://blog.csdn.net/kwang0131/article/details/51085734

swap(a,j,p)

第五题:程序填空-递归
对于f(int a[],int k,int m,char b[]).a[] 是每个国家的最多指派人数,k表示当前是哪个国家,m表示还需要派送几个人(可以为负数).b表示已经派送的人的字符串。

所以这个题目在递归中间的的 第一个循环表示从0~a[i]中让i国选择指派人数,内循环只是向b[]记录的过程。

f(a,k+1,m-i,b)

第六题:
dfs先填数然后判断周围是否可行,八数码问题。

#include<iostream>
#include<cmath>
using namespace std;
int map[3][4];
int vis[10];
int flag[3][4];
int dir[8][2]={1,0,0,1,0,-1,-1,0,-1,-1,1,1,1,-1,-1,1};
int ans=0;

void init(){
    int i,j;
    for(i=0;i<3;i++){
        for(j=0;j<4;j++){
            flag[i][j]=1;
        }
    }
    flag[0][0]=0;
    flag[2][3]=0;
    memset(vis,0,sizeof(vis));
}

void Solve(){
    int i,j;
    int dx,dy;
    bool book=true;
    for(i=0;i<3;i++){
        for(j=0;j<4;j++){
            if(flag[i][j]==0) continue;
            for(int k=0;k<8;k++){
                dx=i+dir[k][0];
                dy=j+dir[k][1];
                if(dx<0||dx>=3||dy<0||dy>=4||flag[dx][dy]==0) continue;
                if(abs(map[dx][dy]-map[i][j])==1){ book=false;break; }
            }
        }
    }
    if(book){ans++;}
}

void dfs(int index){
    int x=index/4;
    int y=index%4;
    if(x==3){
        Solve();
        return ;
    }
    if(flag[x][y]){
        for(int i=0;i<10;i++){
            if(!vis[i]){
                vis[i]=1;
                map[x][y]=i;
                dfs(index+1);
                vis[i]=0;
            }
        }
    }
    else{
        dfs(index+1);
        }
    }

int main(){
    init();
    dfs(0);
    cout<<ans<<endl;
    return 0;
}

暴力,依旧可以用生成全排列的方法先填数,然后再判断是否行可行。next_penutation(a,a+n);

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int a[10]={1,2,3,4,5,6,7,8,9,10};
int ans=0;
int main(){
    do{
        int q1=abs(a[0]-a[1])-1;
        int q2=abs(a[0]-a[3])-1;
        int q3=abs(a[0]-a[4])-1;
        int q4=abs(a[0]-a[5])-1;
        int q5=abs(a[1]-a[2])-1;
        int q6=abs(a[1]-a[5])-1;
        int q7=abs(a[1]-a[6])-1;
        int q8=abs(a[2]-a[6])-1;
        int q9=abs(a[3]-a[4])-1;
        int q10=abs(a[3]-a[7])-1;
        int q11=abs(a[3]-a[8])-1;
        int q12=abs(a[4]-a[8])-1;
        int q13=abs(a[4]-a[5])-1;
        int q14=abs(a[4]-a[9])-1;
        int q15=abs(a[5]-a[6])-1;
        int q16=abs(a[5]-a[9])-1;
        int q17=abs(a[1]-a[4])-1;
        int q18=abs(a[2]-a[5])-1;
        int q19=abs(a[4]-a[7])-1;
        int q20=abs(a[5]-a[8])-1;
        int q21=abs(a[6]-a[9])-1;
        int q22=abs(a[7]-a[8])-1;
        int q23=abs(a[8]-a[9])-1;
    if((q1&&q2&&q3&&q4&&q5&&q6&&q7&&q8&&q9&&q10&&q11&&q12&&q13&&q14&&q15&&q16&&q17&&q18&&q19&&q20&&q21&&q22&&q23)!=0){
            ans++;
        }
    }while(next_permutation(a,a+10));
    cout<<ans<<endl;
    return 0;
}

第七题:剪邮票问题
开始写这道题目的时候一直不知道怎么判断5个数是不是连在一起。参考别人的思路终于搞懂了这道题目。
首先先用stl中的next_permutation生成5组数。
然后dfs判断是否相连。

for(int i=0;i<3;i++){
            for(int j=0;j<4;j++){
                if(!vis[i][j]&&ai[i][j]){
                    num++;
                    dfs(i,j);
                }
            }
        if(num==1) sum++;

这个部分写的非常有趣。它的意思是如果我一次dfs遍历过后,如果存在被标记为1的a[i][j](及我们涂色的方格)没有被访问过,那么证明这次我们涂得颜色不相连。应为一次dfs把所有相连的格子都标记了。

#include"iostream"
#include"algorithm"
#include"string.h"
using namespace std;

int ai[3][4];
int bi[12]={0,0,0,0,0,0,0,1,1,1,1,1};
bool vis[3][4];
int num;
int sum=0;
int dir[4][2]={1,0,-1,0,0,-1,0,1};

void dfs(int r,int c){
    if(r<0 ||r>=3||c<0||c>=4) return ;
    if(vis[r][c]||!ai[r][c]) return ;
    vis[r][c]=true;

    for(int i=0;i<4;i++){
        int x=r+dir[i][0];
        int y=c+dir[i][1];
        dfs(x,y);
    }
}

int main(){
    do{
        memset(vis,false,sizeof(vis));
        num=0;
        int flag=0;
        for(int i=0;i<3;i++){
            for(int j=0;j<4;j++){
                ai[i][j]=bi[flag++];
            }
        }

        for(int i=0;i<3;i++){
            for(int j=0;j<4;j++){
                if(!vis[i][j]&&ai[i][j]){
                    num++;
                    dfs(i,j);
                }
            }
        }
        if(num==1) sum++;
    }while(next_permutation(bi,bi+12));
    cout<<sum<<endl;
    return 0;
}

第八题:四平方和问题
暴力,可以开一个三层遍历,第四层的数可以用总和减去求出来。(如果遍历四层就会爆掉,==先前写错了哎)

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int N;
bool flag=false;

int main(){
    int i,j,k;
    double p;
    cin>>N;
    for(i=0;i*i<N;i++){
        for(j=i;j*j<N;j++){
            for(k=j;k*k<N;k++){
                int q=N-i*i-j*j-k*k;
                //判断q是不是平方数
                p=sqrt(q);
                if(p==int(p)){ flag=true; break;}
            }
            if(flag) break;
        }
        if(flag) break;
    }
    cout<<i<<" "<<j<<" "<<k<<" "<<p<<endl;
    return 0;
}

第九:交换瓶子
贪心。
将要求瓶子的序号存储在数组B中,遍历数组A,如果A中当前位置的瓶子序号不对,就交换当前位置的瓶子和要求序号瓶子的位置。记下交换次数。

#include<iostream>
using namespace std;
#define maxn 100010
int a[maxn],b[maxn];
int ans=0;

int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        b[i]=i+1;
    }
    for(int i=0;i<n;i++){
        if(a[i]!=b[i])
        {
            int temp;
            for(int j=0;j<n;j++)
            {
                if(a[j]==b[i])
                {
                    temp=a[j];
                    a[j]=a[i];
                    a[i]=temp;
                    ans++;
                    break;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

第十:不会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值