Showing posts with label topcoder. Show all posts
Showing posts with label topcoder. Show all posts

Tuesday, May 29, 2007

07年5月29日 在复旦大学的topcoder比赛

先是匹萨,棒约翰的,还不错,我和肖各吃了两块,就饱了,其实是不太好意思吃多 ^_^

然后是比赛,感觉脑子的转速要比在家里做快得多,时间也貌似比一般的一个半小时长得多(因为单位时间的思考能力强了,所以感觉时间就多了)。算是三校联赛吧,被复旦踩是必然的,目标是踩东华。最后338.31,是room2的第7,divsion的第13,还是被两个东华的踩了。

很久没写tc报告了,因为很久不关心算法。但今天还是满有意思的,写一下,纪念一下:

总得来说DIV2的题目就是比较简单的呀。

problem 250:
一个Set包括0-9个数字,其中6和9可以互用,隐含的意思就是可以表示 66 或 99 或 69。
然后给个门牌号,问至少买多少Set能够摆出这个门牌号。

算法很简单,统计一下门牌号中出现过的数字个数。因为6和9可以互用,所以把6的个数和9的个数平均一下,有两个写法:


// method one, after counting
count[6]=count[9]=(count[6]+count[9]+1)/2; // forget add one will be chanllenged

// method two, in counting iteration
if(count[6]<count[9]) count[6]++;
else count[9]++;


看到两个人用第一种写法忘记+1,cha之~,HOHO,赚100分。

problem 500:
有金G银S铜B三种钱币,去银行转换的规则如下:
11 S -> 1 G
11 B -> 1 S
1 G -> 9 S
1 S -> 9 B
问从G1 S1 B1换到 G2 S2 B2的最少交换次数,或-1表示不可能

与其说是贪心,不如说是逻辑题,只要依存简单的逻辑,就能既保证代码清晰,又可保证准确率:
step 1. 如果B不够,只能用S换B
step 2. 如果G不够,只能用S换G
step 3. B和G都够了,若S不够,先用G换S,再用B换S。因为G换S一次可以满足的S多,所以先G换S。

5555,前面的代码都是好好的,可惜最后在B换S的地方,忘记减去B,加上S了。。。好粗心啊 >.<
一开始沈发现了,但他给的cha数据没能把我cha掉~,洋洋得意地笑沈时,忽然某人把我cha了~ 瞬间郁闷

problem 1000:
比赛的时候想了n套方案,结果还是没能决定用什么方法解之。
题目意思是给出一个序列,要求用最小的cost排序,将i放到某个值后面/前面,花费的cost是i。

大大的程序千奇百怪,有STL库牛人的,有搜索解的,有DP的,不过最欣赏的是这个解法:
可以把问题转换为, 求顺序的最大cost的序列,然后用总cost减一下就行了。

例如sample 中的 6 4 5 3 8 2 7 2 11 2 2,顺序序列可以是 4 5 8 11,也可以是4 5 7 11,对于一个顺序序列,剩余的部分便是待移动的数,为了保证待移动的数的cost尽可能小,就是保证顺序序列的cost尽可能大,所以取 4 5 8 11 的cost和为28,所以只需要用最少52-28=24来完成排序。按照这个思路,有程序:


public int calcMinimalCost(int[] arr){
int total=0,len=arr.length,maxCost=0;
int[] cost=new int[len];

for(int i=0;i<len;++i){
cost[i]=arr[i];
total+=arr[i];

for(int j=0;j<i;++j){
if(arr[j]<=arr[i] && cost[j]+arr[i]>cost[i]){
cost[i]=cost[j]+arr[i];
}
}
maxCost=Math.max(cost[i],maxCost);
}

return total-maxCost;
}

Saturday, April 14, 2007

2007年4月的第二周

这一周很忙,也很闲。
首先是上周五,毕业设计需要我去合作的那家单位走一趟。早早地我就起床了,按着昨日网上找好的路线找了2个半小时左右,后来与老师电话后才知道,我找错单位了 -_-b 。随后老师让我不用去了,他们谈好了再通知我。心中一边抱怨着这个不知道在瞎忙什么的毕业设计,一边
低着头沮丧得走着那2小时的回家路。

周一、周二,我奉献给了学校,也就是我那毕业设计。因为了是签了合同的项目,老师又希望我冲优,所以我一直也不敢怠慢。但是,那个单位不懂装懂的一套莫名的号称“创新”的设计实在是把我惹得对该项目厌恶之极。两天的下午,我就坐在那里(傻傻地),装着一些我认为几乎没有价值的,至少对我的毕设而言是没价值的,却又是相当复杂的系统(globus toolkit)。而我要做的那部分(portal),已经完全被搁置了,写完前端后一直等那个单位给我接口,但最后等到的,除了“下周给”还是“下周给”。不是说他们不干事,真的,为什么这么一家还算不错的公司竟然效率这么低呢。

周三,topcoder的marathon结束了。由于浪费了太多时间在毕设上,周三想恶补一下tc的,但最后还是没能如愿,反而最后一次提交的成绩还不如之前的那次好。说实话,这次的marathon是很有趣的,我真的满想静下心来认真做一下。但是除了毕设,周四还有一个相当重要的面试。

周三早5点,我起床,为了周四不知道,周三先去摸摸情况。2小时的路程将我整得相当疲惫,又是2小时的回程,回到家里人像一滩泥,散在椅子上了。不过我硬撑着,如果现在睡了,那么晚上我一定睡不着,所以为了明天早起,不能睡!

周四早5点,起床,准备就绪,出门。今天有个大面试,之所以如此重视它,除了公司名气相当大之外,还有两个原因: 一是已经有我的两个好伙伴收到了公司offer(就是他们推荐我的),为了我们能一起在这家公司里闯事业,我很希望能够进这家公司;二是该公司的面试十分专业,除了让我感受到了公司招人的诚心之外,公司的办事效率也相当值得称赞。面试要持续到下午,做了10道左右的题目,其中写了完整程序的有5道好像。有一道卡住一会,但在面试官的提醒下还是说出了解题的关键算法。还有一道与面试官在题意上有冲突,虽然一开始和面试官有点交流不畅,但后面的两个问题还是解决得满顺的。第二面十分完美,除了题目在很短的时间内做出来以外,中间发生了一段小插曲:我的肚子叫了(-_-b 早饭没吃饱啊),面试官很友善地给我拿了咖啡和饼干,咖啡很好喝。另外,最后一位面试官送我走之前,给了我一个KFC汉堡包,^_^,对公司好感度顿时增加到100%!总体感觉还是不错的,事后我有发觉我的程序还是有漏洞的,但我想结果并不重要,我把我解决问题的思路和方法展现给了面试官,所以面试还是成功的。

面试结束后,我去超市买了不少吃的,脑力和体力消耗太多,需要补一下。晚7点,做tc算法的round 1c,虽然人还是有点疲倦,但听说过round 1就有飞盘~,拼了!第一题很容易就解决了。第二题卡了,写了个DP,但结果始终不对。想到了二分答案,但是我不会写二分答案的算法(知道有点像二分搜索,但因为从来没写过,一下子也摸不着头脑)。结果只做了第一题,最后的结果是排名152名好像。晋级是没有问题的,只是只做了一题,始终感觉不是很爽。过两天就是round 2,+U。

今天marathon成绩出来了,排名150+,不理想,rating也跌了不少。另一件关于tc的事是我的blog增加了一个看tc算法赛事的widget。原本我用flash写的一个,有图片,类tc个人资料的那个flash的。但后来发觉导出成swf就怎么都连不上topcoder,那就拿不到feed了,但是exe和直接在flash IDE下调试是完全成功的。郁闷,不能出swf那就不能挂在blog上了,所以花了半天时间再写了一个javascript的,只是是文字,跟图表的效果是没法比的。



附加一个用CSS 做 tooltip的好文章链接:
http://www.communitymx.com/content/article.cfm?cid=4E2C0&print=true#

为什么我一开始说很忙又很闲呢,忙得是这周事情不少,闲的是大部分事情都只是在花时间和体力,比如毕设、flash的tc rating表白做了和面试那两天的8个小时路程,总有一种在浪费时间的感觉。

Tuesday, April 03, 2007

TCO Marathon Online Round #2

TCO Marathon OR2 finished. I got 65/445 rank, 11331.73 score, and advance to round 3 successfully. My friend, FinalLaugh, got rank 191, while he has got 200 rank when the submission parse finished, just by a finger's breadth. The path to Las Vegas is becoming more and more narrow, next time , we will fight for 50 contestants position.

The top 2 players' program scares me a lot...... So many codes that looks like "AA>s;oI2A". As we, FinalLaugh and I, discussed, it's a technology of compress.

I dislike this problem, two reasons: 1st, it's a gambling game; 2nd, it's solution is not so hard, but with a lot of work. My solution is so easy to implement , somewhat like saarixx (rank 7) did.

First of all, list all card combinations: {4,4} {3,3} ... 15 cases from high to low. Then, provide a simple solution to newcard(), round1(), draw() then take them into an array, each owns 15 elements, just like this:


 private int[] newc = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
private int[] rd1 = { 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
private int[] draw = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 };



For these three method, I think, a fixed strategy will be ok. As to round2(), it's more complexity, but as I'm so lazy.... I realize it like this:


   public int round2(int card1, int card2, int bets1, int bets2, int drew) {
int idx = getCardIdx(card1, card2);

// pre solution, like the too little card will return 0 immediately

switch (drew) {
case 2:
// some solution
case 1:
// some solution
case 0:
// some solution
}
return -1;
}



That's all, so simple but strong enough to advance to the next round. Wish my good luck next round!

Friday, March 30, 2007

TCO Marathon Online Round #1

TCO Marathon OR1 and OR2 has finished today, which consume my thoughts for two weeks.

To OR1, I got 1309.01 at submission phase and 4990.66 at end, final rank 67/532. See the problem here(need login), which is a really interesting and challenge game. As my solution, the image could be considered as a onion, the target of this prob is to peel the onionskin. So, here is the steps of my algorithm:

1. Generate the rays, those rays will be the easy calculating ones. (Attention, generate rays does not mean call the measure() method.)
2. Pick out the rays that just cross one unit('x' unit), and store them in a queue.
3 Iterate the selected rays, calculate the density of that unit(call measure() here), and then mark the unit as calculated.
4 Repeat step 2, but the more repetition we used, the more precision we will lost. It should be a bound to control the precision before we start this algorithm.

As to step one, the rays should be selected meet the condition that they will be easy to calculate, otherwise, it will be a great amount work of calculation and simulation. As I considered, each ray will start from one of the four corners of the unit, and the ray should cross exactly n row unit while it crossed 1 col unit, and vice versa. The main reason I ensure this condition is that every length of the row unit( according to my example) that the ray would cross is the same, and that would lower the complexity of the ray calculation. As a result, when n is greater than 30(I forget the exactly number, but 30 is enough), every unit will be covered.

As to step four, the repetition times is a hard decision. The performs of different repetition times would result in a normal distribution, and the peak of the distribution is the one we desired. I choose the repetition according to a great amount of test.

Wednesday, February 21, 2007

Topcoder SRM340 DIV II

首先叹一下只能沦落在Div2和Div1的边缘。颇为伤感,以后想做Component了。

多么戏剧性的一场比赛啊,第一题还是很稳健的敲掉了,毕竟DIV2第一题太没搞头了。第二题其实也很简单,但比赛的时候,人就容易犯糊涂。 我把第二题先想成dfs,写完后发觉超时,郁闷。然后越想越复杂,想到了DP,DP的路就越走越远拉。最后是235.85收场。

第二题,其实枚举和贪心就行,巨汗呐。不过在Challenge阶段,表现神勇啊!一路从18冲进前10。主要是靠事前准备的对付第二题dfs的数据,哈哈,果然有用dfs还不知情的,连掐3个 ,HOHO。当时排名第10, score 385.85。

最后的System Test是关键!第三题全军覆没,房间里没人过。第二题就第一个人过了。然后,因为我掐了三个人,所以我的总积分排第二!巨汗啊,居然排到了No2,不枉我通宵比赛,呵呵。总结一下,第二题我其实TEST数据早过了,但由于我确定我的程序不完美,所以我一直不交。看来战术是正确的!如果交了被掐掉,那就很尴尬了。

按规则,这场比赛有奖金可以拿,多少无所谓,只要确实有拿就好。拿到钱得请梁大吃饭!梁大应该是说比我做的好,但是最后也是只有一题过了,再加上没掐,所以分数比我差。当然他们房间的整体实力可能还比我这强一点。

Thursday, February 08, 2007

Topcoder Marathon 11

Marathon的System Test也是Marathon式的,等了好久。


最后的Rank终于出来了,Rank 8, Score 388.10, Rating 1565。
第一名好夸张,有好多Case都是超我一倍的呀!赞~


第一次做Marathon,这次的题目是贪吃蛇,郁闷...是比较没新意的题目...个人感觉贪吃蛇运气因素较大(测试数据多的话,当然可以降低偶然性),没有觉得能在每盘上都赢得最高分的算法,但确实应该有能保证在大多数情况下表现出色的算法。
我的算法可以说是偶然性十足 -_-b,我也很纳闷,但就是没法解释,所以只能说偶然。Example Test 15次,Submittion 4次, Submittion的成绩是 30.76 -> 28.44 -> 28.13 -> 27.43 一个比一个差 -_-b (但我的想法好象是一个比一个周密才对呀)。

我的算法的思路是这样的:

Step 1. 将Snake的一次行为(调用 moveSnake())划分为三个小算法, 即计算路径、选路径、移动。

Step 2. 初始化地图我不算在算法里,因为太简单了。计算路径是指,用搜索类的算法,搜索出从Snake到Food的可能路径。

在这一步,我起初使用的是最简单的bfs(就是我得分最高的时候 -_-b)。优点是找到的豆路径最短,缺点是Snake老是擦豆而过,因为路径只关心最短的问题,如果路径上没有经过某个豆,那么即使该豆可以顺便吃掉,Snake也会置之不理。
然后,我改进了算法,使用pfs,以吃到的豆的个数为优先级别进行路径搜索。这样每次都是从吃豆最多的路径继续往下搜,就可以保证将顺路的豆子都能吃掉。结果是,这个pfs每次比bfs走的步数要少,从虚拟程序上看,Snake聪明了许多,但就是吃豆数不见长。

我这有一个我没去实现的算法(因为后面两天都有事),想法是使用多端bfs:Snake头和各个Food各准备一个队列,然后每个循环,依次对每个队列进行扩展。当某个Food队列扩展的路径碰到了Snake的路径,那么Snake到该Food有路;若是Food队列碰到Food队列,那么这两个Food有路。且所有路径最短。改算法的好处是能求出所有最短路径、而复杂度与bfs相同,只是实现有点复杂。

Step 3.选路径,在我自己测试的时候发觉,选路径对于整体结果影响最大!也可以说是偶然性最大的一块。依据Step2中的bfs或者pfs所得到的结果,应该说Snake到Food的路径是固定的,所以就可以说是选下一个受吃的Food。怎么选Food呢?
我给每个Food设置了三个值:
  1. 吃到该Food的路径上顺便可以吃到的Food
  2. 假设Snake吃该Food,那么吃到Food后,Snake的可移动空间,即一次bfs从Food点开始计算空间(要先模拟好Snake吃到Food的位置)。
  3. 该区域内还有多少未吃的Food,即如果Snake逃不出该Area,可能还有多少Food可以吃。
综合上述三点,可以计算出一个优先级。我以Area大小和Snake蛇身长度为主要依据,若蛇身长远远超过Area那么Snake应该说可以有更大的活动,也可以说Snake有机会逃出该Area。再依据Snake吃该Food时顺便吃的Food和该Area潜在的Food同样影响这个优先度。若优先度相似,则可能再吃的Food数量加上顺便吃的Food数量为第二优先级。
在这里,Area的关系十分重要,很明显的,因为Area表示Snake存活概率高,只要活着就不怕没Food吃。
比如下面两个情况:

# ###
#O # #
# #O#

很明显,这些Food是DeathFood,优先级要最低,也就是说实在没Food可吃才吃他们。

对于多端bfs,选择的就不是Food了,而是真正的Path。这个就可能和前面的算法完全不同了,我又没实现多端bfs,而且这个貌似更加复杂,就没深入。。。另一方面是被偶然性搞怕了,深怕花了大半天写的程序结果还不如以前的好。

Step 4.移动,即与平台交互,这个只要认真看看平台文档就行了。另外,为了保持Snake和Food位置与平台同步,自己也要模拟Snake的移动。

附加一个想法,由于Step3提到,Snake吃到Food后的Area问题。所以我考虑是否可以通过预广搜一次,标记所有的Area(或者这里称Prison,也就是整个Area有一个格子负责与外界连着,其他格子均与非此Area的格子无连接)。起算法是,由任意一点,开始bfs,但搜索到的格子只有一个目(类似于围棋的目,就是下面这种情况,X是搜索过的格子,#是障碍物,@就是只有一个目):

XX#
XX@
XX#

这种情况下,将@放入一个Door队列(初始为空)。若搜索第二次遇到@,则@不是Door,标记为搜索过的格子。在待搜索队列为空时,若Door个数大于1,则Area不是Prison,可以再扩展;否则该Area为Prison,同时去除该Door。然后任取一个外面一个没有搜索过的格子再bfs,同样,若搜索到某个Door则取消它Door的资格,否则搜索完再计算Door个数。
可能出现这种情况: Prison - Door - 2个Door的Area - Door ,此时,2个Door的Area不是Prison,但它加上里面的Door和Prison就是一个Prison。可以说是有层次关系的。
总之,算法很复杂,当时摆着电脑楞了许久,最后还是决定先暂时把这个想法搁着 -_-b 。

Friday, January 26, 2007

Topcoder SRM336 DIV II

又回来做Topcoder了,用Ubuntu就是爽啊,又快又华丽,破Windows上Topcoder会有问题。最近Vista的漏洞频频被揭,微软信用大大受损,相反的,Solaris一方面与Intel达成战略合作,另一方面Solaris在争取PowerPC的营地。

学校的网络真是一团糟! 我只能找个HTTP代理,用HTTP的管道上topcoder。时不时就掉下线来。

比赛依然是紧张激烈的,这次是在DIV II 里,rating大概是房间里排第三 1157分。 三道满简单的题目,都是在时间内做出来的:
237.65/250 - 383.94/500 - 0.00/900
其中900的那题,我初次提交是580分好象,后来发现漏了一个case,急啊,赶紧在比赛结束前一分钟改过来(汗,真的是结束前一分钟啊,看着秒数动的,那个心跳啊),得292.85。

challenge阶段网络麻烦不断啊,每每打开别人的代码就会断线,浪费了好多时间。而challenge第一次失败了,虽然我找出了别人的bug,但数据没出好,第二次才成功挑战掉。 我challenge的是900的那道中score有重复的情况,这也是我后来发现自己没考虑到的一个case: {3,3,3} 1 4,如果不考虑重复会得结果 -1,但是正确结果是4。

System Test的最后结果是 900分的Failed,郁闷-_-b,不过还好,还是第三。现在rate 1231, -_-b 再接再历啊。