Advertisement

网易游戏雷火2020春招游戏研发工程师笔试题0425 前三题题解

阅读量:

第一题大概题面:
在这里插入图片描述

思路:dfs/bfs,直接计算答案呢不好算,我们考虑先设ans=6*n,然后把多算的面(内部的面)减掉,考虑一个立方体的坐标为(x,y,z),很容易得到与它相邻的6个面的坐标,如果这些坐标也有立方体,就减去相应的贡献即可,注意每次dfs/bfs的时候需要把一个连通块内的编号设置为统一的,防止死循环。

复制代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e4+5;
    
    int n,ans;
    int x[maxn],y[maxn],z[maxn];
    int d[6][3]={{-1,0,0},{1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
    int vis[21][21][21];
    
    void dfs(int x,int y,int z,int ct)
    {
    vis[x][y][z]=ct;
    int dx,dy,dz;
    for(int i=0;i<6;i++)
    {
        dx=x+d[i][0];
        dy=y+d[i][1];
        dz=z+d[i][2];
        if(dx<0||dx>20||dy<0||dy>20||dz<0||dz>20||!vis[dx][dy][dz])
            continue;
        ans--;
        if(vis[dx][dy][dz]!=ct)
            dfs(dx,dy,dz,ct);
    }
    }
    //给出n块积木的坐标 n<=1e4 0<=x,y,z<=20
    //积木为正方体 边长为1
    //积木可以悬空
    //求这个立体结构的表面积
    //10分
    int main()
    {
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>x[i]>>y[i]>>z[i];
        vis[x[i]][y[i]][z[i]]=1;
    }
    ans=6*n;
    int ct=2;
    for(int i=0;i<n;i++)
    {
        if(vis[x[i]][y[i]][z[i]]==1)
            dfs(x[i],y[i],z[i],ct++);
    }
    cout<<ans<<endl;
    }

第二题大概题面:
在这里插入图片描述

更详细的题解可以看这一篇:<>

复制代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e5+5;
    
    int n;
    int a[maxn];
    //求矩形的最大面积
    //力扣原题 单调栈可解
    //20分
    int main()
    {
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    a[n]=-1;
    stack<int> s;
    ll ans=0;
    for(int i=0;i<=n;i++)
    {
        if(s.empty()||a[i]>=a[s.top()])
            s.push(i);
        else
        {
            int tmp;
            while(!s.empty()&&a[i]<a[s.top()])
            {
                tmp=s.top();
                s.pop();
                ans=max(ans,(i-tmp)*1ll*a[tmp]);
            }
            s.push(tmp);
            a[tmp]=a[i];
        }
    }
    cout<<ans<<endl;
    return 0;
    }

第三题大概题面:
在这里插入图片描述

思路:爆搜?O(10^n)即便加了剪枝也只能过百分之20左右的样例。显然不是正解。考虑用dp[i][a][b][j]表示前i位数字的和为j,第i位数字为b,第i-1位数字为a时的方案数,那么对于满足:(a*100+b*10+c)\%x=0c,我们可以得到转移方程:dp[i][b][c][j]+=dp[i-1][a][b][j-c]显然还需要满足:a+b+c<=j<=s。最终答案是什么呢,显然就是所有的dp[n][a][b][s]之和,枚举a、b即可得到结果。总复杂度O(n*10*10*s)=O(100*n*s),考虑n、s的取值范围,大概在5e^6,实际上应该会更快,因为加了剪枝。

复制代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mod=1e6+9;
    
    int n,s,x;
    int dp[51][10][10][1000];
    
    //n位数字 可以有前导零
    //满足所有数字加起来的和等于s
    //任意三位连续数字构成的三位数可以被x整除
    //这样的数字成为神奇数字 求神奇数字的个数
    
    int main()
    {
    cin>>n>>s>>x;
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<10&&i+j<=s;j++)
            dp[2][i][j][i+j]=1;
    }
    for(int i=3;i<=n;i++)
    for(int a=0;a<10;a++)
    for(int b=0;b<10;b++)
    for(int c=0;c<10;c++)
    {
        if((a*100+b*10+c)%x)
            continue;
        for(int j=a+b+c;j<=s;j++)
            dp[i][b][c][j]=(dp[i][b][c][j]+dp[i-1][a][b][j-c])%mod;
    }
    int ans=0;
    for(int a=0;a<10;a++)
        for(int b=0;b<10;b++)
            ans=(ans+dp[n][a][b][s])%mod;
    cout<<ans<<endl;
    return 0;
    }

第四题:感觉算个大模拟吧,写了一半不想写了溜了orz

全部评论 (0)

还没有任何评论哟~