字节8月21日 笔试第2题走迷宫,第4题 摇骰子比大小
第二题用了dfs(好像用bfs会更简洁)
#include<vector>
using namespace std;
// #include<algorithm>
#include<iostream>
// write your code in C++ (C++14 (g++ 6.2.0))
int ans = 1;
bool dfs(vector<vector<char>> &maze, vector<vector<int>> &visited, int i, int j, int m, int n) {
if(i<0 || i>=m || j<0 || j>=n) { //碰到边
return 0;
}
if(maze[i][j] == 'O') {
return 1;
}
if(maze[i][j] == 'N') { //碰到走不通的路
return 0;
}
if(visited[i][j] == 1) return 0; //已经走过的路
if(visited[i][j] == 2) return 0; //传送带
bool res;
switch(maze[i][j]){
case '.':
visited[i][j] = 1;
res = dfs(maze, visited, i+1, j, m, n) || dfs(maze, visited, i-1, j, m, n)
|| dfs(maze, visited, i, j+1, m, n) || dfs(maze, visited, i, j-1, m, n);
break;
case 'R':
visited[i][j] = 2;
res = dfs(maze, visited, i, j+1, m, n);
break;
case 'L':
visited[i][j] = 2;
res = dfs(maze, visited, i, j-1, m, n);
break;
case 'U':
visited[i][j] = 2;
res = dfs(maze, visited, i-1, j, m, n);
break;
case 'D':
visited[i][j] = 2;
res = dfs(maze, visited, i+1, j, m, n);
break;
default:
res = 0;
break;
}
if(res){ //走的通的路标记为‘O’
maze[i][j] = 'O';
ans++;
visited[i][j] = 0;
cout<<i<<"\t"<<j<<"\t"<<int(res)<<"\t"<<ans<<endl;
return 1;
}else if(visited[i][j]==2){ //走不通的路标记为‘N’,
maze[i][j] = 'N'; //res==0的时候如果是在‘.’上不能判定走不通,因为实际情况可以往回走
// visited[i][j] = 0;
return 0;
}else{
visited[i][j] = 0;
return 0;
}
}
int main(){
//输入操作略
// int m, n;
// cin>>m>>n;
// vector<vector<int>> maze(m,n);
//测试用例
int m = 5, n = 5;
vector<vector<char>> maze = {{'.', '.', '.', '.', '.'},
{'.', 'R', 'R', 'D', '.'},
{'.', 'U', '.', 'D', 'R'},
{'.', 'U', 'L', 'L', '.'},
{'.', '.', '.', '.', 'O'}};
// int m = 3, n = 4;
// vector<vector<char>> maze = {{'O', 'U', '.', '.'},
// {'L', '.', '.', '.'},
// {'.', '.', '.', '.'}};
// maze[m-1][n-1] = 'O';
vector<vector<int>> visited(m, vector<int>(n,0));
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(maze[i][j] != 'O' && maze[i][j]!='N'){
dfs(maze, visited, i, j, m, n);
}
}
}
cout << m*n-ans<< endl;
return 0;
}
第4题大致思路:用an,bn表示两个数组大小,suma,sumb表示数组中所有元素总和,如果摇骰子每次为结果都是1,那么结果就是数组大小,如果每次都是最大值,那么结果就是数组所有元素总和。
对于每个骰子,每一个面朝上概率是一样的,这意味着每个人的每个结果点数和的概率都是一样的,所以只要统计每组数所有可能的总和的个数就可以最后算出概率,
例如如果a = {8}, 那么可能有8种和即1~8,每种和只有一种情况,b = {2, 3, 4},就可能有2+3+4 -3+1= 7种和(最小为3对应每个骰子恰好都是1朝上,最大是9对应每个骰子都恰好是最大值朝上)每种和对应的情况数可能不同,比如和为4的情况有3种,分别是[1, 1, 2], [1, 2, 1], [1, 1, 2],需要用dfs统计每个和的情况次数 。
ps:因为要算a组数赢的概率,所以最后比较的是a的所有情况总和中大于b的情况,这里就有剪枝的空间了: 如果 a的个数都比b的总和要大了那肯定赢,返回1.0,反之肯定输,返回0.0。
相应的,用dfs计数的时候也只需要统计最后需要比较的情况,所以dfs也可以剪枝,这里懒得写了。。。
#include<vector>
using namespace std;
#include<algorithm>
#include<iostream>
#include<unordered_map>
#include<iomanip>
// write your code in C++ (C++14 (g++ 6.2.0))
//dfs计算掷完一组骰子每个值可能出现的次数
void dfs(vector<int> &A, unordered_map<int, int> &hashm, int cursum, int n, int depth) {
if(depth == n) {
hashm[cursum]++;
return ;
}
for(int i=1; i<=A[depth]; i++){
cursum += i;
// cout<<cursum<<":"<<hashm[cursum]<<"\t";
dfs(A, hashm, cursum, n, depth+1);
cursum -= i;
}
}
int main(){
// int an, bn;
// cin>>an>>bn;
// vector<int> A(an), B(bn);
int an = 1, bn = 3;
vector<int> A = {8}, B = {2, 3, 4};
int suma = 0, sumb = 0;
double p_a = 1.0, p_b = 1.0;
for(int i=0; i<an; i++) {
// cin>>A[i];
suma+=A[i];
p_a *= 1.0/A[i];
}
for(int i=0; i<bn; i++){
// cin>>B[i];
sumb+=B[i];
p_b *= 1.0/B[i];
}
if(suma<=bn){
cout << setprecision(3) << fixed << 0.0<< endl; //控制小数位输出
return 0;
}
if(sumb<an){
cout << setprecision(3) << fixed << 1.0<< endl; //控制小数位输出
return 0;
}
unordered_map<int, int> hash_a;
unordered_map<int, int> hash_b;
dfs(A, hash_a, 0, an, 0);
dfs(B, hash_b, 0, bn, 0);
int start, end;
if(bn>an) start = bn+1;
else start = an;
end = suma;
// cout<<endl;
// cout<<an<<"\t"<<suma<<"\n"<<bn<<"\t"<<sumb<<endl;
// cout<<"p:"<<p_a<<"\t"<<p_b<<endl;
// cout<<"start:"<<start<<"\t"<<end<<endl;
double ans = 0.0;
for(int i=start; i<=end; i++){
for(int j=bn; j<i; j++){
ans += hash_a[i]*p_a*hash_b[j]*p_b;
// cout<<i<<":"<<hash_a[i]<<"\t"<<j<<":"<<hash_b[j]<<endl;
}
// cout<<ans<<endl;
}
cout << setprecision(3) << fixed << ans<< endl;
}

哔哩哔哩公司氛围 725人发布