校招全国统一模拟笔试(二月场)编程题参考思路及代码
独立的牛牛
题目分析
首先计算能保证的房屋能租多少天,如果有剩余再考虑购买水果。
参考代码
#include <bits/stdc++.h>
using namespace std;
int x, f, d, p;
int solve(int x, int f, int d, int p) {
int tmp1 = d / x;
if(tmp1 <= f) return tmp1;
d -= f * x;
return f + d / (x + p);
}
int main() {
cin >> x >> f >> d >> p;
cout << solve(x, f, d, p) << endl;
return 0;
}
牛牛吃雪糕
题目分析
我们要按照一定的策略来安排这些雪糕来让能撑过的天数最大。
首先我们考虑只吃一盒两份或者一盒三份的雪糕,那么每天我们吃3盒每盒两份的雪糕或者2盒每盒三份的雪糕。接下来用一盒一份的雪糕来填补空隙。空隙从小到大依次是:1盒两份+1盒三份的组合缺1盒一份,2盒两份的组合缺2盒一份,1盒三份的组合缺3盒一份,1盒两份的组合缺4盒一份。按照这个顺序依次填补存在的空隙,剩下来的每盒一份的雪糕,每6盒撑过一天。最后答案取决于能撑过的天数和高温天数的大小比较。
参考代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, a, b, c;
scanf("%d", &t);
while(t--) {
scanf("%d%d%d%d", &n, &a, &b, &c);
n -= c / 2;
c = c % 2;
n -= b / 3;
b = b % 3;
if(a >= 1 && b >= 1 && c == 1) {
a--;
b--;
c--;
n--;
}
if(b == 2 && a >= 2) {
b = 0;
a -= 2;
n--;
}
if(c == 1 && a >= 3) {
c = 0;
a -= 3;
n--;
}
if(b == 1 && a >= 4) {
c = 0;
a -= 4;
n--;
}
n -= a / 6;
a = a % 6;
if(n > 0)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}
牛牛炒股票
题目分析
题目可以被抽象为一个多重背包:我们把借来的钱看成容量,买入价看成物品的重量,卖出价看成物品的价值。答案就等于总价值和总重量的差值。
注意处理所有股票都处于跌价状态的情况。
参考代码
#include <bits/stdc++.h>
using namespace std;
int dp[1005];
int c[1005][2];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) dp[i] = i;
for(int i = 1; i <= n; i++) {
scanf("%d%d", &c[i][0], &c[i][1]);
for(int j = c[i][0]; j <= m; j++)
dp[j] = max(dp[j], dp[j-c[i][0]] + c[i][1]);
}
printf("%d\n", dp[m] - m);
return 0;
}
牛牛打响指
题目分析
按照题目描述的那样去模拟就可以得到答案。唯一的问题是N太大了无法表示,所以我们把数字分割成很多位来处理,需要采用高精度加法和高精度除以2两种操作。
注意处理N=999这种过程中会超出N长度的情况。注意处理N=1的情况。
参考代码
#include <bits/stdc++.h>
using namespace std;
char s[105];
int main() {
int l, ans = 0, tops = 1, now;
scanf("%s", s + 1);
l = strlen(s + 1);
for(int i = 1; i <= l; i++) s[i] -= '0';
while(tops < l || s[tops] != 1) {
ans++;
if(s[l] % 2) {
now = l;
s[now]++;
while(s[now] == 10) {
s[now - 1]++;
s[now] = 0;
now--;
if(now < tops) tops = now;
}
} else {
for(int i = tops; i <= l; i++) {
if(s[i] % 2)
s[i + 1] += 10;
s[i] = s[i] / 2;
if(i == tops && s[i] == 0)
tops++;
}
}
}
printf("%d\n", ans);
return 0;
}
牛牛取快递
题目分析
实际上题目要求我们分别求出从S到T和从T到S的最短路再把他们加起来。所以我们只要分别以S和T为起点跑单源最短路,再把两次的终点的坐标加起来就可以了。
注意图是有向图。
参考代码
#include <bits/stdc++.h>
using namespace std;
struct Edge
{
int dis,to;
bool friend operator <(Edge x1,Edge x2)
{
return x1.dis>x2.dis;
}
}temp,now;
vector <Edge> vec[10005];
bool life[10005];
int dis[10005],n;
priority_queue <Edge> q;
void init()
{
for(int i=1;i<=n;i++)
dis[i]=100000000;
memset(life,0,sizeof(life));
while(!q.empty())
q.pop();
}
int dij(int s,int t)
{
init();
temp.to=s;
temp.dis=0;
q.push(temp);
dis[s]=0;
while(!q.empty())
{
now=q.top();
q.pop();
if(!life[now.to])
{
life[now.to]=1;
for(int i=0;i<vec[now.to].size();i++)
{
if(!life[vec[now.to][i].to] && dis[now.to]+vec[now.to][i].dis<dis[vec[now.to][i].to])
{
dis[vec[now.to][i].to]=dis[now.to]+vec[now.to][i].dis;
temp.to=vec[now.to][i].to;
temp.dis=dis[vec[now.to][i].to];
q.push(temp);
}
}
}
}
return dis[t];
}
int main()
{
int m,s,t,u,v,d;
scanf("%d%d%d%d",&n,&m,&s,&t);
while(m--)
{
scanf("%d%d%d",&u,&v,&d);
temp.dis=d;
temp.to=v;
vec[u].push_back(temp);
}
printf("%d\n",dij(s,t)+dij(t,s));
return 0;
}
#校招#