资格赛只要做出一道题便可以,因为LOL比赛的关系也只是草草的做了一下,发现微软出题还是很有趣的,所以来整理一下~~~~(>_<)~~~~
发现微软的面试题目,很侧重于先推导中间结论,简化算法复杂度的思路,这也是我很喜欢的,虽然我的数学很弱。⊙﹏⊙b
//--------------------------------------------------------------------------------------格叽格叽------------------------------------------------------------------------------------------------------------------
传话游戏
描述
Alice和Bob还有其他几位好朋友在一起玩传话游戏。这个游戏是这样进行的:首先,所有游戏者按顺序站成一排,Alice站第一位,Bob站最后一位。然后,Alice想一句话悄悄告诉第二位游戏者,第二位游戏者又悄悄地告诉第三位,第三位又告诉第四位……以此类推,直到倒数第二位告诉Bob。两位游戏者在传话中,不能让其他人听到,也不能使用肢体动作来解释。最后,Bob把他所听到的话告诉大家,Alice也把她原本所想的话告诉大家。
由于传话过程中可能出现一些偏差,游戏者越多,Bob最后听到的话就与Alice所想的越不同。Bob听到的话往往会变成一些很搞笑的东西,所以大家玩得乐此不疲。经过几轮游戏后,Alice注意到在两人传话中,有些词汇往往会错误地变成其他特定的词汇。Alice已经收集到了这样的一个词汇转化的列表,她想知道她的话传到Bob时会变成什么样子,请你写个程序来帮助她。
输入
输出
对于每组测试数据,单独输出一行“Case #c: s”。其中,c 为测试数据编号,s 为Bob所听到的句子。s 的格式与输入数据中Alice所想的句子格式相同。
数据范围
小数据:1 ≤ N ≤ 100, 1 ≤ M ≤ 100, 1 ≤ len ≤ 10000
大数据:1 ≤ N ≤ 100000, 1 ≤ M ≤ 100000, 1 ≤ len ≤ 1000000000
思路以及代码
#include <iostream>
#include <map>
#include <sstream>
using namespace std;
int T,C;
int n,m;
string tarstr;
stringstream ss;
string t,tt;
map<string,string> varstr;
int main()
{
cin>>T;
C=0;
while(T--){
C++;
cin>>n>>m;
varstr.clear();
for (int i=0;i<m;i++){
cin>>t>>tt;
varstr[t]=tt;
}
cin.ignore(256,'\n');
getline(cin,tarstr);
ss.clear();
ss<<tarstr;
cout<<"Case #"<<C<<":";
while(ss>>tarstr){
for (int i=0;i<n-1;i++){
if (varstr.find(tarstr)==varstr.end()) break;
tarstr=varstr[tarstr];
}
cout<<" "<<tarstr;
}
cout<<endl;
}
}
长方形
描述
在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。
输入
输入文件包含多组测试数据。
第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。
每组数据为三个用空格隔开的整数 N,M,K。
输出
对于每组测试数据,输出一行"Case #X: Y",其中X表示测试数据编号,Y表示最多能找到的符合条件的长方形数量。所有数据按读入顺序从1开始编号。
数据范围
0 ≤ K ≤ N * M
小数据:0 < N, M ≤ 30
大数据:0 < N, M ≤ 30000
思路及代码
#include <iostream>
#include <map>
#include <sstream>
#include <math.h>
using namespace std;
int T,C;
long n,m,k,ans,t,nt,mt,kt,addm,addn;
long max(long a,long b){
if (a<b) return b;
else return a;
}
int main()
{
cin>>T;
for (C=1;C<=T;C++){
cin>>n>>m>>k;
if (n<m) {
t=n;
n=m;
m=t;
}
ans=0;
for (nt=1;nt<=n;nt++){
t=0;
mt=k / nt;
if ((mt<=m) && (0<mt)){
t+=(mt-1)*(nt-1)*mt*nt>>2;
kt=k-nt*mt;
addm=0;
addn=0;
if (0<kt){
if ((kt<=mt) && (nt+1<=n))
addn=nt*kt*(kt-1)>>1;
if ((kt<=nt) && (mt+1<=m))
addm=mt*kt*(kt-1)>>1;
t+=max(addn,addm);
}
}
ans = max(ans,t);
}
cout<<"Case #"<<C<<": "<<ans<<endl;
}
}
树上的三角形
描述
输入
接下来有 T 组数据,每组数据中:
第一行包含一个整数 N,表示树上节点的个数(从 1 到 N 标号)。
接下来的 N-1 行包含三个整数 a, b, len,表示有一根长度为 len 的树枝/树干在节点 a 和节点 b 之间。
接下来一行包含一个整数 M,表示询问数。
接下来M行每行两个整数 S, T,表示毛毛虫从 S 爬行到了 T,询问这段路程中的树枝/树干是否能拼成三角形。
输出
接下来对于每个询问输出一行,包含"Yes"或“No”,表示是否可以拼成三角形。
数据范围
小数据:1 ≤ N ≤ 100, 1 ≤ M ≤ 100, 1 ≤ len ≤ 10000
大数据:1 ≤ N ≤ 100000, 1 ≤ M ≤ 100000, 1 ≤ len ≤ 1000000000
思路以及代码
int calc(int x, int y){
int a = x, b = x, res = 2, c;
while(b <= y){c = b; b = a + b; a = c; res++; }
return res;
}
其他路径很短的情况,需要排序来判断。
//第三题来自mochavic
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
int deep[100010], f[100010][2];
vector<int> e[100010];
int c[60], cn;
void dfs(int fa, int x, int d){
int i, y;
deep[x] = d;
for (i = 0; i < (int)e[x].size(); i += 2){
y = e[x][i];
if (y == fa) continue;
f[y][0] = x;
f[y][1] = e[x][i + 1];
dfs(x, y, d + 1);
}
}
void pd(int x, int y){
while (deep[x] > deep[y]){
c[cn++] = f[x][1];
x = f[x][0];
if (cn == 50) return;
}
while (deep[y] > deep[x]){
c[cn++] = f[y][1];
y = f[y][0];
if (cn == 50) return;
}
while (x != y){
c[cn++] = f[x][1];
x = f[x][0];
c[cn++] = f[y][1];
y = f[y][0];
if (cn >= 50) return;
}
}
int main(){
int T, ri = 1, n, m, x, y, z, i;
scanf("%d", &T);
while (T--){
scanf("%d", &n);
for (i = 1; i <= n; i++) e[i].clear();
for (i = 1; i < n; i++){
scanf("%d%d%d", &x, &y, &z);
e[x].push_back(y);
e[x].push_back(z);
e[y].push_back(x);
e[y].push_back(z);
}
dfs(0, 1, 0);
printf("Case #%d:\n", ri++);
scanf("%d", &m);
while (m--){
scanf("%d%d", &x, &y);
cn = 0;
pd(x, y);
sort(c, c + cn);
for (i = 0; i + 2 < cn; i++){
if (c[i] + c[i + 1] > c[i + 2]) break;
}
if (i + 2 < cn) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}