第四天项目算是告一段落,经过这几天的大起大伏,我做的东西基本达到了能够拿出去展示的效果,Min就要带着这个版本去英国给那边的人展示了。今天见到了不少好玩的玩意,发现微软就是有钱啊,在办公室设施上不吝惜金钱,在研究设备上更不吝惜金钱。最好玩的东西是Min带去英国用用来演示的SONY UX系列超小型的笔记本电脑了。贴俩图:

ux_02.jpg

ux_08.jpg

这个小东西厚是厚了一点,但是性能…快赶上我自己的本了,这个配置用来打魔兽世界应该也一点不卡,就是屏幕小了一点,分辨率又很高,看不清楚。总之,这一天的最好的事情就是我写的程序顺利移植到这台机器上了,并且效果也是我们希望的那样。希望Min的英国之行顺利。

今天在转移程序间隙中和UI组的哥哥聊了聊,他来了三个月了,是北京交通大学的研二学生,读交通专业的,让我很吃惊。

后面的工作就是继续整理原来的代码,争取在扩展性上有大的突破吧。晚些时候Mentor给我讲了讲他正在做的核心的工作,希望我能够在这个方面帮助他们。讲了一堆微软内部使用的版本控制工具,听得我云里雾里,这才发现为什么微软不让用盗版软件的另一个原因:你需要的软件微软自己都开发了一份…下面的工作等星期一再说吧,因为要等Mentor把需要给我的资料整理一下才能开展工作。

第三天是忙碌的一天。由于项目赶得紧,编码工作很紧张。开始的时候,Mentor原意是让我在一个现有的代码上提取出我们需要的部分,我看了一下代码,由于我对那块技术不了解,或者说根本不会,所以想单独写一个出来。第三天的全天都在努力的写代码。早晨很早就来了,六点半坐下就开始写代码,一直写到吃饭,吃完饭回来接着写,这时候发现我使用的方法跟原来用重量级库的方法效果不能比,可能进一步优化会使得效果差不多,但是毕竟时间有限。于是下午的时候Mentor跟我一商量,决定先修改原来的代码,改到我们需要的效果之后先用了再说,于是终于可以从压力巨大的写代码中脱离出来,进入了另一个迷宫…

然后下午晚些的时候,Mentor一直去开会,我改出来的效果想叫他看看,也没见着他人,只好早早先去吃饭,结果刚打好饭吃了每两口,电话打来了,说是大家要讨论一下,看一下效果~于是乎就只好赶紧塞两口进去,回到5楼来。看效果的人声势浩大,俩员工,其中一个是负责拿着这份程序给别人演示的姐姐。还有两个UI组的实习生,准备今天能把UI做好给我。头一回有UI支持的我还有点不适应,这个等UI拿来再细讲。

视察完之后主要对参数调整和UI不满意,我在想,我半天改出来的东西能有多好….再给我一天时间叫你们开开眼…哈哈哈

不管怎么样,晚上还要接着改,到8点半的时候,趁着Mentor还没走,我把修改的成果给他看了看,还算满意。之后我就回旅馆了。

本人不是很会写文章,不是不会写,是没空写。所以一般写出来的东西都是流水账一样那种。各位看客见谅。昨天是进入微软实习的第二天,才两天功夫我就发现我完全融入了这个环境当中。一大早六点半起来收拾妥当就前往麦当劳餐厅,那个地方吃饭比较便宜,啃个麦香鱼汉堡,虽不至于吃饱,但至少不会感到饿,唉,我们当学生的,还是在为温饱而奔波啊。

早早来到公司,公司里还没多少人,第一天晚上比较累,就早早地走了,不知道这边员工和学生晚上都工作到几点,反正我同住的博士大哥都是快12点才回来睡觉,和他住了三天没说过几句话呢。不过早起的员工还真的没多少。因为门卡还没办好,只好还是请保安开门,进来发现,早上7点多的时候,只有不到5个人在,不知是早起一族还是熬夜到现在。

上午没什么,还是继续老老实实编程,中午吃了俩纯素菜,没要汤,10块。

好玩的事情发生在下午,下午两点半来到一间会议室参加NIO(New Intern Orientation),还是我们一起进来的实习生在一起听各个部门的实习生讲规则规矩之类的。方方面面讲了很长时间,尤其是法律部门,关于版权、专利之类的注意事项讲了很多,看来微软真的是被告怕了~NIO结束之后,我和另外一位注册比较早的实习生拿到了门卡,从此成为了“有卡一族”,可以出入自由啦,真正的想几点来几点走随便了。顺便说一句,门卡押金50,真贵啊。能不能留个做纪念…

晚上小小努了一把力,工作到9点,喝了杯咖啡,不怎么困呢。其实晚上留下来加班的员工和实习生都不是很多,员工大概有一小半吧,一般做到8点也就回了,估计是家里还是要照顾一下。实习生如果是外地的,就什么时候困了什么时候回去,反正旅馆里没有网络,还不如在公司爽。

自从上次写完参加毕业典礼的日志之后就没闲着过。先是搬家,累的要死,那段时间把东西统统打包,再搬到将来住宿的14号楼去,每天能够坐在电脑前面的时间不足1小时,而多半那一小时靠电影来打发,因为我需要吃东西…一般就是一边吃一边看了。一个电影几个小时,我用几天才能看完。

再后来,东西渐渐搬走了,再剩下的就要么打包进随身的包,要么丢掉了。这样的抉择导致我随身的包相当重。然后上了飞机,因为北京方面天气的原因,我和200多人挤在767飞机里傻坐了俩小时。有人有意见,我没有,350块买的机票,能有啥意见~

爸爸这段时间恰好在北京出差,然后妈妈也专程来看看我,于是一家三口在这样的机遇下在北京有了一天时间。我们去了和绅的恭王府,然后就是天安门广场。送我到了MSRA安排的住处,父母就回去了。

MSRA工作地点在北京海淀区知春路西格玛大厦,这个地方地理方位极佳,周边一圈大学,紧靠城铁(上海称轻轨)站,离三环四环都不远。我们外地来的实习生住在西格玛后面的一个小旅馆,旅馆条件比较一般,但是收拾得相当干净。据前台服务员讲,这个旅馆基本全部被MS的实习生所占据。和我同住的是中科大的博士,学电子的,压力大啊~

进来第一天,上午按时去西格玛五层前台报到,保安发给一个”Visitor”的胸卡,领到了”九龙”会议室。会议室里已经坐了将近10个人,男男女女都有,瞄了一眼,大部分还是北京附近高校的,航空航天、北大之类的。可能MS招这样的人成本较低吧,毕竟招来外地的,每天还要多付75块的住宿费给旅馆。负责实习生check-in的HR小姑娘(她应该不会看到这篇吧…?)不久就来了,我还搞不清楚情况,不过从她Email地址看,也是v-打头的,难道也是实习生?来了一后发给大家一堆表格文件之类的,主要就是实习协议、一些说明,和保密协议中英文各一份。签好之后又填一份办银行卡的单子,以后的补助就发在这里。至于补助的金额,HR姐姐不许说,我就讲,比想像中略少,与学历有关。顺便说一句,和我一起开会的10个人,我是年纪和年级最小的。

然后HR姐姐带着10几个新VS(Visiting Student)浩浩荡荡地挨个找Mentor,沿途员工和VS前辈都盯着看,很好玩的样子。MSRA工作环境还算很可以的,到处收拾得很干净,不像很多中国软件公司里面,桌子上都一层灰,员工自己不擦就没人擦。我属于DIT组,找到Mentor之后HR姐姐就和其他VS走了,剩下的事情都是我的Mentor和我解决了。Mentor先介绍了周围几个员工,然后让我把电脑设置好。可能是由于我晚报到的缘故吧,我的东西都准备好了。桌子上的名字牌也做好了,电脑主机上也贴上了橘黄的标签,写上了我的名字,Email帐号,Mentor名字,使用期限和座位号。

使用HR姐姐发的帐号密码登陆进主机后,改了密码,仔细观察观察这台机器的情况。配置基本是最高的,不至于因为配置原因降低工作效率。软件环境全部英文的,从系统到Office到VS都是。还好这几个软件用起来都比较熟悉,不至于摸不着地方。

设置好电脑,Mentor带领我来到UI组的实习生那里,给我简单看了我需要做的东西的效果,回来给了我代码和部分文档,就开始工作啦。

西格玛大厦吃饭巨贵,俩菜一碗稀饭,大概3两米饭,打卡打掉20,想想在学校,这样的菜最多6块。唉,还是多吃吃麦当劳吧。

先写这些吧,别的再说。8:36了,人陆续来了。开工吧。

今天中午,收到微软的接收通知,本来昨天等了一整天第四个面试电话,结果等到10点多也没来,心情不好就直接睡觉去了,没想到今天一起床插上电话线就收到微软打来的接收电话。确定6月25日出发去北京。一个暑假这样过,也许比在家里自己造点东西更有意义吧。

上张挺有意思的图:
200705150949514dcc7.jpg

P.S. 今天还拆掉了我的IBM R51,本来准备换根灯管,结果…新灯管有点长,被我试图剪掉一部分金属导电端时不小心…断了…只好再装起来。庆幸我没先焊下旧的来才发现新的长…

今天中午就接到MSRA的第二个电话面试,有点奇怪,因为前面几个电话都是晚上,我一直以为微软的前辈们都按照美国时间工作…结果今天在我午睡正香的时候打来了电话,开始问了几个项目的事情,我晕晕乎乎答得语无伦次,我明白他想知道关于开发中遇到的难题,然后我是怎么克服的,无奈实在不清醒…都想不起来了,结果我想他没有得到太多想得到的吧。之后,给我出了一个简单的算法题目要求写出来,听工程院实习的同学讲,当面面试的时候都会直接写在白板上,然后由微软的人录入编译的,这样放给我自己做,我觉得还算是降低难度了吧。

题目是这样的:有一个矩阵,每个元素是一个数,要求,从左上角出发到达右下角,每次只能向右或向下,要求全路线经过的元素和最小,求出路径及这个和的值。要求分别用递归和非递归方法实现之。
结果图:
matrix1.jpg
我花了一下午,写出了这个程序,幸运的是,两种方法的结果竟然相同…
哈哈~~玩笑话,放出代码:

[code=’c#’]
using System;
using System.Collections.Generic;
using System.Text;

namespace Matrix
{
class Program
{
///

/// 矩阵元素的最大值,用于生成随机矩阵
///

private static int MAX_ELEMENT = 10;
///

/// 矩阵的高度
///

private static int MATRIX_X = 4;
///

/// 矩阵的宽度
///

private static int MATRIX_Y = 15;

///

主函数

/// 命令行参数 static void Main(string[] args)
{
//初始化一个目标矩阵
int[,] matrix = new int[MATRIX_X, MATRIX_Y];
//初始化一个方向矩阵
string[,] direction = new string[MATRIX_X, MATRIX_Y];
//随机生成目标矩阵的元素
Generate(ref matrix, MATRIX_X, MATRIX_Y);
Console.WriteLine(“Target Matrix is:”);
//打印矩阵
PrintMatrix(matrix, MATRIX_X, MATRIX_Y);

//递归法
Console.Write(“\r\nMethod No.1 Result\r\nMinCost=” + Step(direction, matrix, MATRIX_X, MATRIX_Y, MATRIX_X – 1, MATRIX_Y – 1));
//打印结果
PrintDirection(direction, MATRIX_X, MATRIX_Y);

//清空方向矩阵
direction = new string[MATRIX_X, MATRIX_Y];
//非递归法
PrintMinCostRoute(direction, matrix, MATRIX_X, MATRIX_Y);
}

///

随机生成目标矩阵

/// 目标矩阵的引用 /// 矩阵宽度 ///矩阵高度 static private void Generate(ref int[,] matrix, int x, int y)
{
//如果未初始化,先初始化之
if (matrix == null)
{
matrix = new int[x, y];
}
//随机生成元素
Random random = new Random();
for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { matrix[i, j] = random.Next(MAX_ELEMENT - 1) + 1; } } } ///

非递归寻找最小值及路径

///路径矩阵 ///目标矩阵 ///矩阵宽度 ///矩阵高度 static private void PrintMinCostRoute(string[,] direction, int[,] matrix, int x, int y)
{
//动态规划备忘录矩阵
int[,] cost = new int[x, y];
//初始化各节点为整型变量最大值
for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { cost[i, j] = int.MaxValue; } } //从左上角逐次扩大矩阵 for (int i = 0; i < (x >= y ? x : y); i++)
{
//左上角
if (i == 0)
{
//就是本身
direction[0, 0] = “S”;
cost[0, 0] = matrix[0, 0];
}
else
{
//顺次检查当前方阵周围的元素
for (int k = 0; k < i + 1; k++) { //如果范围合法 if (i < x && k < y) { //检查比较当前的最小值和从上面过来的值 if (cost[i, k] >= (cost[i – 1, k] + matrix[i, k]))
{
//上面更小则更新
cost[i, k] = cost[i – 1, k] + matrix[i, k];
direction[i, k] = “U”;
}
if (k >= 1)
{
//检查比较当前的最小值和从左面过来的值
if (cost[i, k] >= (cost[i, k – 1] + matrix[i, k]))
{
//左面更小则更新
cost[i, k] = cost[i, k – 1] + matrix[i, k];
direction[i, k] = “L”;
}
}
}
//如果范围合法
if (i < y && k < x) { //检查比较当前的最小值和从上面过来的值 if (cost[k, i] >= (cost[k, i – 1] + matrix[k, i]))
{
//上面更小则更新
cost[k, i] = cost[k, i – 1] + matrix[k, i];
direction[k, i] = “L”;
}
if (k >= 1)
{
//检查比较当前的最小值和从上面过来的值
if (cost[k, i] >= (cost[k – 1, i] + matrix[k, i]))
{
//左面更小则更新
cost[k, i] = cost[k – 1, i] + matrix[k, i];
direction[k, i] = “U”;
}
}
}
}
}
}
Console.Write(“\r\n\r\nMethod No.2 Result\r\nMinCost=” + cost[x – 1, y – 1]);
PrintDirection(direction, x, y);
}

///

一步递归求某位置的最小值

///路径矩阵 ///目标矩阵 ///矩阵宽度 ///矩阵高度 ///位置x坐标 ///位置y坐标 /// 这个位置的最小值
static private int Step(string[,] direction, int[,] matrix, int x, int y, int pos_x, int pos_y)
{
//Debug用
//Console.WriteLine(“pos_x=” + pos_x + “,pos_y=” + pos_y);
//第一行的元素
if (pos_x == 0)
{
//第一个元素,递归结束,返回本身的值
if (pos_y == 0)
{
//特殊位置,路径指向Self=”S”
direction[pos_x, pos_y] = “S”;
//返回本身的值
return matrix[pos_x, pos_y];
}
//第一行非第一个,必然从左边走过来
else
{
//路径指向Left=”L”
direction[pos_x, pos_y] = “L”;
//左边一个的最优值加上本身得到最优值
return Step(direction, matrix, x, y, pos_x, pos_y – 1) + matrix[pos_x, pos_y];
}
}
//第一列的元素,必然从上边走过来
if (pos_y == 0)
{
//路径指向Up=”U”
direction[pos_x, pos_y] = “U”;
//上边一个的最优值加上本身得到最优值
return Step(direction, matrix, x, y, pos_x – 1, pos_y) + matrix[pos_x, pos_y];
}
//避免重复计算,先取到上面一个和左边一个的最优值
int up = Step(direction, matrix, x, y, pos_x – 1, pos_y);
int left = Step(direction, matrix, x, y, pos_x, pos_y – 1);
//如果从上面走合算
if (up <= left) { //路径指向Up="U" direction[pos_x, pos_y] = "U"; //上边一个的最优值加上本身得到最优值 return up + matrix[pos_x, pos_y]; } //如果从左面走合算 else { //路径指向Left="L" direction[pos_x, pos_y] = "L"; //左边一个的最优值加上本身得到最优值 return left + matrix[pos_x, pos_y]; } } ///

打印矩阵

/// ///矩阵宽度///
///矩阵高度
static private void PrintMatrix(int[,] matrix, int x, int y)
{
for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { Console.Write(matrix[i, j].ToString() + " "); } Console.Write("\r\n"); } } ///

打印所走的路径矩阵及走法

///路径矩阵 ///路径矩阵宽度 ///路径矩阵高度 static private void PrintDirection(string[,] matrix, int x, int y)
{
//打印路径矩阵
Console.WriteLine(“\r\nThe Direction Matrix:”);
for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { Console.Write(matrix[i, j] + " "); } Console.Write("\r\n"); } //打印走法 Console.Write("The Route is:"); //走法的逆序存放数组 string[] Reverse = new string[x + y - 2]; int pos_x = x - 1; int pos_y = y - 1; //从终点开始向路径矩阵指示的方向回溯走法 for (int i = 0; i < (x + y - 2); i++) { //从左边来的 if (matrix[pos_x, pos_y].Equals("L")) { pos_y--; Reverse[i] = "right"; } //从上边来的 else { pos_x--; Reverse[i] = "down"; } } //倒序打印走法的逆序存放数组,得到真正的从起点出发的走法 for (int i = 0; i < (x + y - 2); i++) { //倒序打印 Console.Write(Reverse[(x + y - 2) - i - 1]); if (i < (x + y - 3)) { //不是最后一个的时候打一个分隔号 Console.Write(","); } } } } } [/code]