————————————————————————————————————————
题目是按照记忆复述的,可能不准确,样例也并非官方样例。
阿里巴巴(4.8) 研发工程师C/C++ 考试时长1h,完成时间40min(AK)
一、有m个小怪兽,每个怪兽有a滴血,我们可进行n次攻击,每次可使其中任意b个怪兽血量减一
输入:n,m,a,b (四个数均在1e9以内)
输出:一个数,表示最多可以杀死几只怪兽
样例:Input:5 5 2 2
Output:5
数据范围决定不可能是模拟题,思考后发现只需要根据怪兽总血量和我方总伤害的关系即可确定答案。(注意特判n是否小于a)
#include
using namespace std;
long long T,n,m,a,b;
int main()
{
cin>>T;
while (T--)
{
cin>>n>>m>>a>>b;
if (n=m*a) cout<
二、给出一张n*n的地图,每个点有一个能量值,从左上顶点出发,每次可以向上下左右某个方向前进,每次最少前进1格,最多前进k格,且所到达的点中的能量值必须比之前所在点的能量值大,每到达一个点可获取该点能量值,输出最终可获得的最大能量值
输入:n,k,n*n的地图 (n<=100)
输出:一个数,最大能量值
样例:Input:3 2
1 2 3
2 5 4
6 8 7
Output:25
从某个点出发可获得的能量值固定,不受之前已获取能量值影响,显然可以用记忆化搜索解决
#include
#define MAXN 105
using namespace std;
int a[MAXN][MAXN];
int dp[MAXN][MAXN];
int T,n,k;
bool check(int x,int y)
{
if (x>0&&y>0&&x<=n&&y<=n) return 1;
return 0;
}
void dfs(int x,int y)
{
if (dp[x][y]!=0) return;
dp[x][y]=a[x][y];
for (int i=1;i<=k;i++)
{
if (check(x,y+i)&&a[x][y+i]>a[x][y])
{
dfs(x,y+i);
dp[x][y]=max(dp[x][y],dp[x][y+i]+a[x][y]);
}
if (check(x,y-i)&&a[x][y-i]>a[x][y])
{
dfs(x,y-i);
dp[x][y]=max(dp[x][y],dp[x][y-i]+a[x][y]);
}
if (check(x+i,y)&&a[x+i][y]>a[x][y])
{
dfs(x+i,y);
dp[x][y]=max(dp[x][y],dp[x+i][y]+a[x][y]);
}
if (check(x-i,y)&&a[x-i][y]>a[x][y])
{
dfs(x-i,y);
dp[x][y]=max(dp[x][y],dp[x-i][y]+a[x][y]);
}
}
}
int main()
{
cin>>T;
while (T--)
{
cin>>n>>k;
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
cin>>a[i][j];
dfs(1,1);
cout<
代码都是考试时写的,不是特别美观
——————————————————————————————————
网易互娱(4.11)游戏开发工程师 考试时长2.5h 完成时间2h (AK)
一、一张n*n的地图,其中某些点有能量球,含有能量 aij,某个人站在(x,y)处(左上为(0,0))并且有一把长为 l 的剑,每次挥剑可将范围内的能量球吸收(以所站点为圆心,剑长为半径),并相应地使剑的长度增加(增加长度等于能量值),问最终剑可以变为多长。(两点间距离定义为欧氏距离)
输入:n,l,n*n的地图,x,y
n<=500
输出:一个数,最终剑的长度
样例:Input:4 1
0 1 0 0
0 1 0 0
0 0 0 0
0 1 2 3
Output:3
把每个点和当前位置的距离算出并放入优先队列中(按距离排序),再依次取出并模拟剑变长的过程
#include
#include
#include
#include
#include
#include
#define MAXN 505
using namespace std;
struct node
{
int p;
double d;
bool operator < (const node &b)const
{
return d>b.d;
}
};
priority_queue Q;
int a[MAXN][MAXN],n,l,T,x,y;
double get_d(int x,int y,int i,int j)
{
return sqrt((x-i)*(x-i)+(y-j)*(y-j));
}
int main()
{
cin>>T;
while (T--)
{
cin>>n>>l;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
cin>>a[i][j];
cin>>x>>y;
x++;
y++;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (a[i][j]!=0)
{
node tmp;
tmp.d=get_d(x,y,i,j);
tmp.p=a[i][j];
Q.push(tmp);
}
}
while (!Q.empty())
{
node tmp=Q.top();
Q.pop();
if (l>=tmp.d)
{
l+=tmp.p;
}
}
cout<
二、集合操作:给出n个正整数(1到n),有m次操作,操作1将x和y两个数所属集合合并,操作2将数x取出单独成为一个集合,操作3询问x所属集合中有几个数。开始时每个数分别属于一个集合。
输入:n,m,m次操作,每行第一个数表示操作类型,后接x,y(或x)
n<1e4 ,m<1e3
输出:对于每个操作3 输出一个答案
样例:Input:4 5
1 1 2
3 2
1 2 3
2 2
3 1
Output: 2
2
两个数组,分别表示每个集合大小,和每个数所属集合。其中集合编号循环使用。
#include
#include
#include
#include
#include
#define MAXN 10005
using namespace std;
int T,n,m,op,x,y,now,tmp;
int size[MAXN],belong[MAXN];
int main()
{
cin>>T;
while (T--)
{
cin>>n>>m;
memset(size,0,sizeof(size));
memset(belong,0,sizeof(belong));
for (int i=1;i<=n;i++)
{
belong[i]=i;
size[i]=1;
}
now=n+1;
while (m--)
{
cin>>op;
if (op==1)
{
cin>>x>>y;
tmp=belong[y];
for (int i=1;i<=n;i++)
{
if (belong[i]==tmp)
{
belong[i]=belong[x];
size[belong[x]]++;
size[tmp]--;
}
}
}
if (op==2)
{
cin>>x;
while (size[now]!=0)
{
now++;
if (now>=10001) now=1;
}
size[belong[x]]--;
belong[x]=now;
size[now]++;
}
if (op==3)
{
cin>>x;
cout<
三、错排问题:给出n个数(1到n)的一个排列,找出与它的距离最小的一个错排,输出最小距离。
错排是指新排列中每个数的位置都与旧排列中不同
对于每个数 i 来说,距离定义为 vi*abs(i 原位置 - i 新位置),其中vi为权值,由v数组给出
排列之间的距离定义为其中每个数新旧位置的距离之和
例如排列 2 3 1 4和排列 3 1 4 2的距离为10 (对于v数组2 2 1 1来说)
注意vi表示i这个数的权值而不是i这个位置的权值(因为这个卡了好一会儿)
输入:n,原排列,v数组
n <= 20
输入样例:4
2 3 1 4
2 2 1 1
输出样例:6
样例解释:原排列与3 2 1 4 距离最近
由n的范围可看出是搜索题,但需要剪枝
不加剪枝可过30%
剪枝一:若距离已超过之前搜索到的最小距离,则回溯 (30)
剪枝二:n为偶数时,每个数都只需移动一格即可达成错排 (40)
剪枝三:每个数移动不超过3格 (即新旧位置相减不超过3)(100)我也不知道为什么正确,凭感觉加的。
此题卡了一个小时,尝试了许多玄学剪枝
#include
#include
#include
#include
#include
using namespace std;
int T,n;
int a[22],v[22];
int sumv;
int ans;
bool vis[22];
void dfs(int s,int d)
{
if (s>n)
{
ans=min(ans,d);
return;
}
if (d>ans) return;
for (int i=1;i<=n;i++)
{
if (i==s) continue;
if (vis[i]==1) continue;
if (abs(i-s)>=3) continue;
vis[i]=1;
dfs(s+1,d+abs(s-i)*v[a[s]]);
vis[i]=0;
}
}
int main()
{
cin>>T;
while (T--)
{
ans=1e9;sumv=0;
memset(a,0,sizeof(a));
memset(v,0,sizeof(v));
cin>>n;
for (int i=1;i<=n;i++)
cin>>a[i];
for (int i=1;i<=n;i++)
{
cin>>v[i];
sumv+=v[i];
}
if (n%2==0) ans=sumv;
else
{
dfs(1,0);
}
cout<
————————————————————————————————
腾讯(3.28)游戏客户端开发岗 考试时长45min
貌似都是牛客网上原题
一、给出int范围内的一个数n,求其二进制中1的个数(负数按补码考虑)
二、单向链表反向与双向链表反向(已给出程序框架)
三、输出字典序最小的最长上升子序列(nlogn)
网上可以搜到就不写题解啦
另外腾讯面试特别喜欢问c++,比如c++11新特性,多态如何实现,c++内存如何分配,可做相应准备