将近2个月没做TopCoder了,似乎官方都不给我发比赛提醒邮件了。。。这次的TopCoder好难,500分的题目最后都没做出来。。。
Div 2 250pt:
题意是给你一个可用天数total和一个去每个城市花费时间的数组d,求最多可以去多少个城市。
非常简单的一道题。容易忽略的地方有两个:一个是天数正好能被用完的情况,一个是数组越界。
Div 2 500 / Div 1 250:
TopCoder的题目少,难度跨度大。。至今还在绿名。。。还要加油啊。。。题意是ICPC的比赛会给解决问题的队伍插气球。要求不同的题目的气球颜色必须不同,想吐题目的气球的尺寸必须相同。给你一个数组balloonCount代表你买的每种气球的个数,字符串balloonSize表示每种气球的大小,数组maxAccepted表示每个题目最多会有多少队伍能解决。问最少需要对多少气球改变颜色。
一开始一点想法都没有,后来看到maxAccepted的长度最多才15,因此想到可以2^15进行枚举哪道题用什么大小的气球。然而之后我就不知道该如何分配气球使得总的改变颜色次数最少。。。最后看了别人的代码才大概有了一点想法。。
首先把题目化简:假如没有大小限制,如何分配气球给不同的题目使得改变颜色最少?
这时,如果题目的数量比气球多,肯定无法完成分配。而如果气球多,则把 题目需求数 和 气球数 都排序,然后从 题目需求数 大的开始,需求最大 和 气球数最多的分配在一起。那么 改变颜色 的次数就是 当 需求数 大于 气球数 时的差值的和。
那么回到原来的问题,只需枚举每个题目使用的是 L 还是 M,那么就变成了两个 简单问题。最后求一个最小的答案即可。 代码如下:
class ICPCBallons { public int minRepaintings(int[] balloonCount, String balloonSize, int[] maxAccepted) { int numTasks = maxAccepted.length; int n = Math.max(balloonCount.length, numTasks); int[] larges = new int[n]; int[] smalls = new int[n]; int largsPtr = 0; int smallPtr = 0; for (int i = 0; i < balloonCount.length; ++i) { if (balloonSize.charAt(i) == 'L') { larges[largsPtr++] = balloonCount[i]; } else { smalls[smallPtr++] = balloonCount[i]; } } Arrays.sort(larges); Arrays.sort(smalls); Arrays.sort(maxAccepted); int res = (int) 1e9; for (int largeSet = 0; largeSet < (1 << numTasks); ++largeSet) { res = Math.min(res, minRepaint(larges, largeSet, maxAccepted, numTasks) + minRepaint(smalls, ((1 << numTasks) - 1) - largeSet, maxAccepted, numTasks)); } if( res >= 1e9) return -1; return res; } private int minRepaint(int[] heaps, int set, int[] maxAccepted, int n) { int ptr = heaps.length - 1; int totalNegative = 0; int totalPositive = 0; for (int i = n-1; i >= 0; --i) { if (((set >> i) & 1) != 0) { int delta = heaps[ptr--] - maxAccepted[i]; if (delta < 0) totalNegative += -delta; else totalPositive += delta; } } while (ptr >= 0) { totalPositive += heaps[ptr--]; } if (totalPositive >= totalNegative) return totalNegative; return (int) 1e9; } }