網易遊戲雷火2020春招遊戲研發工程師筆試題0425 前三題題解

第一題大概題面:
在這裏插入圖片描述

思路:dfs/bfsdfs/bfs,直接計算答案呢不好算,我們考慮先設ans=6nans=6*n,然後把多算的面(內部的面)減掉,考慮一個立方體的座標爲(x,y,z)(x,y,z),很容易得到與它相鄰的66個面的座標,如果這些座標也有立方體,就減去相應的貢獻即可,注意每次dfs/bfsdfs/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;
}

第二題大概題面:
在這裏插入圖片描述

更詳細的題解可以看這一篇:https://blog.csdn.net/xiji333/article/details/104885433

#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(10n)O(10^n)即便加了剪枝也只能過百分之2020左右的樣例。顯然不是正解。考慮用dp[i][a][b][j]dp[i][a][b][j]表示前ii位數字的和爲jj,第ii位數字爲bb,第i1i-1位數字爲aa時的方案數,那麼對於滿足:(a100+b10+c)%x=0(a*100+b*10+c)\%x=0cc,我們可以得到轉移方程:dp[i][b][c][j]+=dp[i1][a][b][jc]dp[i][b][c][j]+=dp[i-1][a][b][j-c]顯然還需要滿足:a+b+c<=j<=sa+b+c<=j<=s。最終答案是什麼呢,顯然就是所有的dp[n][a][b][s]dp[n][a][b][s]之和,枚舉aba、b即可得到結果。總複雜度O(n1010s)=O(100ns)O(n*10*10*s)=O(100*n*s),考慮nsn、s的取值範圍,大概在5e65e^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;
}

第四題:感覺算個大模擬吧,寫了一半不想寫了溜了orzorz

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章