随手练——【2015蓝桥杯】试题

1.奖券数目

作答:52488,正确

#include <iostream>
using namespace std;

bool check(int x) {
    int a[10] = { 0 };
    while (x) {
        a[x % 10]++;
        x /= 10;
    }
    if (a[4] != 0)return false;
    return true;
}

int main() {
    int res = 0;
    for (int i = 10000; i <= 99999; i++) {
        if (check(i)) {
            res++;
        }
    }
    cout << res << endl;
    return 0;
}

2.星系炸弹

作答:2017-8-5,正确

基本功,日期判断 -_-。

#include <iostream>
using namespace std;

int main() {
    //根据2014年的来写的
    int days[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
    int year = 2014, month = 11, day = 9;

    for (int i = 0; i < 1000; i++) {
        cout << year << " " << month << " " << day << ": " << i << endl;
        day++;
        if (day == days[month] + 1) {
            month++;
            day = 1;
            if (month == 13) {
                year++;
                if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))days[2] = 29;
                else days[2] = 28;
                month = 1;
            }
        }
    }
    cout << year << " " << month << " " << day << endl;
    return 0;
}

3.三羊献瑞

作答:1085,正确

有进位,那么“三”一定是1,那么“祥”一定是9,那“羊”一定是0,但是“瑞”+“羊”又不是“瑞”,所以“生”+“献”有进位,那“生”就是“瑞”+1。(我只剪枝到加粗的部分,答案就一秒跑出来了,不需要继续剪枝了。)

有头脑的暴力搜索:

#include <iostream>
using namespace std;

bool check1(int x) {
    int a[10] = {0};
    while (x) {
        a[x % 10]++;
        x /= 10;
    }
    for (int i = 0; i <= 9; i++) {
        if (a[i] > 1)return false;
    }
    return true;
}
bool check2(int i,int j) {
    int a[10] = { 0 };
    int rui = j % 10;
    if (i / 100 % 10 != j % 10)return false;
    while (i&&j) {
        a[i % 10]++; a[j % 10]++; i /= 10; j /= 10;
    }
    for (int i = 0; i <= 9; i++) {
        if (i == rui)continue;
        if (a[i] > 1)return false;
    }
    return true;
}
bool check3(int i, int j, int k) {
    int a[10] = { 0 };
    if (k / 10000 != 1)return false;
    if (k / 1000 % 10 != 0)return false;
    if (k / 100 % 10 != i / 10 % 10)return false;
    if (k / 10 % 10 != j % 10)return false;
    while (i&&j) {
        a[i % 10]++; a[j % 10]++; i /= 10; j /= 10;
    }
    if (a[k % 10] != 0)return false;
    return true;
}

int main() {
    for (int i = 9123; i <= 9876; i++) {
        if (!check1(i))continue;
        for (int j = 1023; j <= 1098; j++) {
            if (!check2(i, j))continue;
            if (check3(i, j, i + j)) {
                cout << i << " " << j << " " << i + j << endl;
                //system("pause");
            }    
        }
    }
    return 0;
}

4.格子中输出

实话实说,不百度,我之前真不知道这个%*s,是怎么用的,比较狠。

printf("%*s", 10, s); /*意思是输出字符串s,但至少占10个位置,不足的在字符串s左边补空格,这里等同于printf("%10s", s);*/

作答:

printf("%*s%s%*s", width/4,"", buf, width/4,"");  //填空
正确答案:(width-strlen(s)-2)/2,"",s,(width-strlen(s)-1)/2,""

备注:答案可以形式多样性,只要代入使得代码成立即可

5.九数组分数

回溯,没看代码猜出来的,那个位置,还能写啥,送人头 -_-

{t = x[i]; x[i] = x[k]; x[k] = t; }

6. 加法变乘法

作答:16,正确

#include <iostream>
#include <queue>
using namespace std;

int sum(int *a,int i,int j) {
    int s = 0;
    for (int k = 1; k < 50; k++) {
        if (k == i) {
            s += a[k + 1] * a[k];
            k++;

        }
        else if (k == j) {
            s += a[k + 1] * a[k];
            k++;
        }
        else
        s += a[k];
    }
    return s;
}
int flag = 0;
void DFS(int *a, int i, int j) {
    if (i == j - 1)return;
    if (sum(a, i, j) == 2015&&(i!=10)) {
        flag = 1;
        cout << i << ' ' << j << endl;
        return;
    }
    if (flag)return;
    DFS(a, i, j - 1);    
    DFS(a, i + 1, j);
}

int main() {
    int a[50];
    for (int i = 0; i < 50; i++)a[i] = i;
    //1,48
    DFS(a, 1, 48);
}

7.牌型种数

答案:3598180

思路:DFS,相当于13个桶,每个桶选的牌数量五种情况 0,1,2,3,4, 到牌数量达到13张。

#include <iostream>
#include <algorithm>
using namespace std;

int res = 0;
void dfs(int pos, int cnt) {
    if (cnt == 13) {
        res++;
        return;
    }
    if (pos == 14) {
        return;
    }
    int num = min(13 - cnt, 4);
    for (int i = 0; i <= num; i++) {
        dfs(pos + 1, cnt + i);
    }
    return;
}
int main() {
    dfs(1, 0);
    cout << res << endl;
    return 0;
}

8.移动距离

刚看题目本来以为是最短路径的计算,其实简单很多,应该是有更便捷的方法,通过运算 O(1)解决,但这样也已经很快了。

#include <iostream>
using namespace std;

int si, sj, ei, ej;
void initialize(int W,int L,int m,int n) {
    int cnt = 1; 
    for (int i = 0; i < L; i++) {
        if (si != 0 && ei != 0 && sj != 0 && ej != 0)break;
        if (i & 1) {
            for (int j = W - 1; j >= 0; j--) {
                if (cnt == m) {
                    si = i;
                    sj = j;
                }
                if (cnt == n) {
                    ei = i;
                    ej = j;
                }
                cnt++;
            }
        }
        else {
            for (int j = 0; j < W; j++) {
                if (cnt == m) {
                    si = i;
                    sj = j;
                }
                if (cnt == n) {
                    ei = i;
                    ej = j;
                }
                cnt++;
            }
        }
        
    }
}

int main() {
    int W, m, n;
    cin >> W >> m >> n;
    //得到最大值
    int MAX = m > n ? m : n;
    //获取当前宽度、最大门牌号下需要的长度是多少
    int L = MAX / W + 1;

    initialize(W, L, m, n);

    int res = abs(si - ei) + abs(sj - ej);
    cout << res << endl;
    return 0;
}

9. 垒骰子

【蓝桥杯】- 垒骰子

10.生命之树

猜你喜欢

转载自www.cnblogs.com/czc1999/p/10380778.html