Southwestern Europe 2005 ——解题报告

Southwestern Europe 2005 ——解题报告

序:
    复旦的教练给了我们一次听ACM讲课的机会,课的进度太快,也没听懂多少,所以问牛人们敲了一套题来做做,就是本文的标题SWERC05的题目。
    题目难度中等略上吧,不过题目数量很多,有10道(吓)。后面的几道题目满有搞头的。
   
A    The mysterious X network:

    求最短路径的简单题,因为权值都是1,所以直接广搜就行了。

B    Bin Packing:

    似乎以前在某个判题的网站上做过这样一道训练题,也是简单题,因为每个item都必须要放在BIN里,所以从一边小到大找,另一边从大到小找,能塞进一个BIN的就塞一个,不能塞进,就将大的那个单独放一个BIN。 如此贪心便可。

C    On Storing Clothes:

    模拟题,并没什么算法,就是要题目看仔细。特别是要注意seperate hook的删除与否,操作W n时判断n-1的seperate hook是否有衣服,无则删除,有则保留,同样判断n+连续的衣服k后的n+k+2是否为衣服,否则删了n+k+1的seperate hook,有则保留。W n后cur指针指在n位置上。

D    Buy or Build:

    算是中等难度的题目吧,还好题目的数据量不是很大,否则算法的要求就高了。因为题目中已声明提供的子网个数十分小(<8),所以对子网的取舍情况共有256种。
    假设点集P,在计算一个已经有子网将部分点连通的点集P1的MST时,不难想到,其还需添加的边是P的MST的边集P-MST的子集,即P1-MST包含于P-MST。所以如果已经求得P-MST的情况下,再求P1-MST的复杂度就是O(n),因为P-MST长度为n。那么,256种情况枚举一下是 256n (n<=1000),不会超时。
    最后的工作是算一下P-MST,因为是欧几里德最小生成树,烦的算法很烦,我是求了O(n^2)条边(即所有边),然后用Kruskal求出MST的。
    PKU上跑了5000MS出头。

E    4 Values whose Sum is 0:

    也是简单题,由于只有4列,所以分成两组 A,B,每组含n^2个元素,即该组两列元素枚举出所有的和。然后A从小到大,B从大到小,找出Ai=(-Bj) 的所有情况,统计一下,就是最后的解。

F    Keep the Customer Satisfied:

    中等难度的题目吧,想了好久才知道用贪心的算法可以O(n)下解决(排序还要nlogn)。
    我想题目的关键是后面的Hint,“They also claim that there is an optimal solution such that for any two orders Ju and Jv with qu > qv and du < dv , if Ju is accepted then Jv is also accepted. ”这句话。意思是,若Ju在最优解中,那么所有du<dv 和 qu>qv的JOB都在最优解内。如何理解呢,首先爱截止日期d排序(这个应该满好理解的),然后我们假设下面的情况:
        i<j        Ji在当前最优解中        Jj的qj<qi
     若将Jj放入最优解中是可以的,即不会超过截止日期,那么将Jj放入最优解,则满足前面说的那个情况(其实保持的是一个最优子结构)。
    若将Jj放入最优解中是不可以的,即会超过截止日期,那么利用贪心选择的性质,可以很容易想到用Jj替换Ji,即Ji不再是最优解元素,Jj放入最优解,简单证明一下解依然是最优的:
    设dn 是当前最优解的任务完成时间,有dn<=di<=dj,而qi>qj,所以 Ji 换成 Jj 后dn=dn-(qi-qj),即dn减小,且JOB数不变,自然要比当前解更优。

    总结一下可以如此贪心:设当前最优解Solu
  1. 依d从小到大排序。
  2. i=0,开始从小到大开始遍历找最优解,若i已到n,则Solu是最优解。
  3. 若JOBi不能放入Solu中,则取当前最优解的q最大元素Solu[k](若Solu[k]==JOBi,跳4),JOBi取代Solu[k]。
  4. i++,跳2。               
   取最大元素可以用堆、优先队列等。

G    UFO Cubes in Roswell:

    这题规模太大,用JAVA内存会溢出,而用C++写我实在不熟练,所以就没过。
    题目意思是从BOX上方射如(SIZE+1)^2的光,在经过BOX内的镜子反射后分别从六个面有多少光射出。
    我原先的程序用了4个MAP,模拟起来不是很烦,只是要记得有光是不会射出去的,需要做判断比较烦。

H    Black Box

    这是一道看上去很难很烦,其实算法不是很深,实现稍需细心的题目。我用JAVA搜是3000MS左右过的,题目要求是5000MS,这题目用搜应该没多大问题。
    题目的规模颇小,6*6的范围取5点也就376992种解,5层递归搜一下便可,稍微复杂的约束函数比较麻烦,因为条件很多,所以要细心加耐心。

    注意的是题目中所说的“be deduced from the experiments”,是指推算出唯一解,想想也知道,不然这题就是Special Judge了。Sample 2就是因为解太多,所以结果是NO。

I    Pixel Shuffle

    这道题目花了我颇多的时间,比赛的时候估计是放弃的题目了。首先排除了暴力法,1000*1000的数组经过2^10变化时间会很长。
    起初我想到的是计算机图形学的基本变换和复合变换,只要求出一套变换的复合矩阵(3*3的),然后求该矩阵左乘自己多少次能变为单位矩阵,就可以知道结果了。不过题目中的后四个变化没办法直接套出变换矩阵,那么就很难求一套变换后的矩阵。

    后来想到的方法是求出一套变换后的图象(一个二维数组),变换后Pij 位置上的值V原来的位置是V/n ,V%n,通过求从某点出发一直到回到该点的环,记下环长度,然后对所有环求一下最小公倍数就可以了。想法是正确的,我想应该是可以过的,不过因为我在MIX的变换中出了点差错,所以我没能写完这个代码。

    最后我用的方法是对于某点(i,j)(而不是整个图)做一套变换成为(ti,tj),然后对(ti,tj)再做他的那套变换,如此反复直到回到(i,j),记下环长度,同时设置所有环内点为已读。这样时间的复杂度是n*n,空间的复杂度只有2。应该说和上一段的思路基本一致,但空间上大大节约了。
    如果问还有什么能提高速度的,我觉得是可以用一个Map记录下已经计算过的变化,即会导致相同环长度的变化,然后对该变化只求一次。因为比较复杂,所以我没有实现。


J    Consecutive ones:

    这是一道搜索题,难度中等。不过貌似求Consecutive ones有专门的算法,反正我是用搜索过的,预先记录下每个人的活动次数cnt[],搜索是先在最左边摆1试试看,然后在他的右边放,不行的话就回朔,这样的解空间树的搜索,应该还是好理解的。
    在搜索到第i个位置时,维护前i-1个解导致的每人活动次数tmpCnt[],对i列的每行j扫描,若为0则要求tmpCnt[j]=0或者tmpCnt[j]=cnt[j]则解是有效的,否则无效。

 

你可能感兴趣的:(java,算法,活动,Build,NetWork,hook)