校招全国统一模拟笔试(七月场)编程题参考代码

膨胀的牛牛

分析

根据题意遇到跟当前大小一样的草料大小翻倍即可。

参考code

#include <bits/stdc++.h>

using namespace std;

const int maxn = 200 + 5;

int a[maxn], n, A;
int main() {
    scanf("%d%d", &n, &A);
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    for(int i = 0; i < n; i++) {
        if(a[i] == A) A += A;
    }
    printf("%d\n", A);
    return 0;
}

黑化的牛牛

分析

一个做法是枚举去除掉的字符然后去重一下。
其实我们仔细观察对于相邻的两个字符如果一样去除掉后一个是不会产生新的字符串的,于是问题就转化为计算字符串当前字符是否和前面字符相同,特殊处理下长度等于1的情况即可。

参考code

#include <bits/stdc++.h>

using namespace std;

string s;
int main() {
    cin >> s;
    int ans = 0;
    for(int i = 1; i < s.size(); i++) {
        if(s[i] != s[i - 1]) ans++;
    }
    if(s.size() == 1) ans = 0;
    ans++;
    cout << ans << endl;
    return 0;
}

黑白卡片

分析

考虑最终的状态只有两种,然后分别比较之后取最小值即可。

参考code

#include <bits/stdc++.h>

using namespace std;

string s;
int main() {
    cin >> s;
    int cnt1 = 0, cnt2 = 0;
    for(int i = 0; i < s.size(); i++) {
        if(i % 2 == 0) {
            if(s[i] != 'W') cnt1++;
        } else {
            if(s[i] != 'B') cnt1++;
        }
    }
    for(int i = 0; i < s.size(); i++) {
        if(i % 2 == 0) {
            if(s[i] != 'B') cnt2++;
        } else {
            if(s[i] != 'W') cnt2++;
        }
    }
    cout << min(cnt1, cnt2) << endl;
    return 0;
}

序列交换

分析

用vector存序列,枚举交换之后丢进set去重得到个数即可。

参考code

#include <bits/stdc++.h>

using namespace std;

int n;
set<vector <int> > s;
vector<int> x;
int main() {
    cin >> n;
    for(int i = 0; i < n; i++) {
        int tmp;
        cin >> tmp;
        x.push_back(tmp);
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i != j) {
                swap(x[i], x[j]);
                s.insert(x);
                swap(x[i], x[j]);
            }
        }
    }
    cout << s.size() << endl;
    return 0;
}

丑陋的字符串

分析

前缀都是'?'部分都是有方案可以抵消掉的。。后面的部分遇到'?'考虑前一个是什么贪心放就好了。

参考code

#include <bits/stdc++.h>

using namespace std;

string str;
int calc(string s, int j) {
    int res = 0;
    for(int i = j + 1; i < s.size(); i++) {
        if(s[i] == s[i - 1]) res++;
    }
    return res;
}
int main() {
    cin >> str;
    int pos = 0;
    while(pos < str.size() && str[pos] == '?') pos++;
    for(int i = pos + 1; i < str.size(); i++) {
        if(str[i] == '?') {
            if(str[i - 1] == 'A') str[i] = 'B';
            else str[i] = 'A';
        }
    }
    cout << calc(str, pos) << endl;
    return 0;
}

庆祝61

分析

枚举排列来计算肯定是不可行的。。
考虑我们已经将身高升序排序了,然后对于前k个小朋友组成队形的身高差的最大值的最小值为f(k),并且第k个和第(k-1)个小朋友是相邻的。现在我们加入第(k+1)个小朋友,考虑到第(k + 1)个小朋友身高是大于等于前面的小朋友,插入队形之后,第(k + 1)个小朋友一定与两个小朋友相邻, 所以当我们将第(k + 1)个小朋友插入到第k个和第(k - 1)个小朋友中间可以得到f(k + 1)的下界一定是max(f(k), h[k] - k[k - 2]),我们又注意到这样插入之后第(k + 1)个和第k个小朋友还是相邻的,于是这样可以一直推广下去。考虑最初3个小朋友的时候这样也是可行的, 于是问题变成了求max(h[i] - h[i - 2])。可以写出很简洁的代码。

参考code

#include <bits/stdc++.h>

using namespace std;

const int maxn = 20 + 5;

int n;
int h[maxn];
int main() {
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%d", &h[i]);
    sort(h, h + n);
    int ans = 0;
    for(int i = 2; i < n; i++) ans = max(ans, h[i] - h[i - 2]);
    cout << ans << endl;
}

随机的机器人

分析

考虑dp[i % 2][j][k]表示走了i步之后恰好有j个红色格子,并且此时机器人正好站在第k个红色格子上的概率。最后求一个可能的状态的带权和就是所求期望。时间复杂度O(n ^ 3)

这个题应该还有很多做法,甚至可以做到O(n^2),O(n),欢迎讨论.

参考code

#include <bits/stdc++.h>

using namespace std;

const int maxn = 500 + 5;

double dp[2][maxn][maxn];
int n ;
int main() {
    cin >> n;
    double ans = 0;
    dp[0][1][0] = 1.0;
    for(int i = 1; i <= n; i++) {
        int cur = i % 2, old = 1 - (i % 2);
        for(int j = 1; j <= i + 1; j++) for(int k = 0; k < j; k++) dp[cur][j][k] = 0;
        for(int j = 1; j <= i; j++) for(int k = 0; k < j; k++) {
            if(dp[old][j][k] > 0) {
                int pos1 = j, pos2 = k + 1;
                if(pos1 == pos2) ++pos1;
                dp[cur][pos1][pos2] += 0.5 * dp[old][j][k];
                int pos3 = j, pos4 = k - 1;
                if(pos4 == -1) {pos3++,pos4++;}
                dp[cur][pos3][pos4] += 0.5 * dp[old][j][k];
            }
        }
    }
    for(int i = 1; i <= n + 1; i++) {
        for(int j = 0; j < i; j++) {
            ans += i * dp[n % 2][i][j];
        }
    }
    printf("%.1f\n", ans);
    return 0;
}

逃离农场

分析

考虑dp[i][k][sum]表示前i个奶牛中选取k个他们的编号和为sum的方案数,于是有:
dp[i][k][sum] = dp[i - 1][k][sum] + dp[i - 1][k - 1][(sum - i + n) % n]
然后可以滚动优化或者压缩一维空间。

参考code

#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;
int n, k;
int dp[55][1005];
int main() {
    cin >> n >> k;
    dp[0][0] = 1;
    for(int i = 0; i < n; i++) {
        for(int j = k; j >= 1; j--) {
            for(int x = 0; x < n; x++) {
                dp[j][x] = (dp[j][x] + dp[j - 1][x - i < 0 ? x - i + n : x - i]) % mod;
            }
        }
    }
    cout << dp[k][0] << endl;
    return 0;
}
#校招##笔试题目#
全部评论
点赞 回复 分享
发布于 2019-07-18 14:58
为什么有这么多题,我写的时候怎么只有最后三题啊?而且我python用动规写的奶牛那题和上面一样但是超内存了,感觉好坑啊。
点赞 回复 分享
发布于 2019-07-19 10:37
请问大家,逃出农场那道题我用python3写的回溯法求解的,我在本地idle都通过了,但是牛客网系统说我的运行时间超了,可是系统给出的时间是处了c类语言外用时不超过4s,平时我在leetcode上写同类的回溯也就48ms之类的运行时间,无解?是对python不友好?代码如下: import sys  def comb(n, k):     result = []     tmp = []     def helper(result, tmp, n, pos, k):         total = sum(tmp)         if k == 0:             if total % n == 0:                 result.append(tmp[:])                 return             else:                 return         for i in range(pos, n):             tmp.append(i)             helper(result, tmp, n, i + 1, k - 1)             tmp.pop()     helper(result, tmp, n, 0, k)     return len(result) for line in sys.stdin:     n, k = map(int, line.split())     print(comb(n, k))
点赞 回复 分享
发布于 2019-07-19 10:53
膨胀的牛牛那道题我也是这么写的。和你一模一样。结果只通过了40%,为啥啊
点赞 回复 分享
发布于 2020-03-19 21:41

相关推荐

jack_miller:我给我们导员说我不在这里转正,可能没三方签了。导员说没事学校催的时候帮我想办法应付一下
点赞 评论 收藏
分享
点赞 26 评论
分享
牛客网
牛客企业服务