狗狗40题

长春赛之前拿来了练练手。这些题都比较简单,放在区预赛大部分应该都是可以看到直接开的题,不过因为毕竟代码量都不少,所以有时却能帮自己发现的点问题所在。

在这里做个简单的题解。


zju1021.The Willy Memorial Program

http://www.shaidaima.com/source/view/11171

管数目不多,管的长度也不多,那么总的蓄水量也很少,因此可以直接模拟滴水的过程,就是一秒一个单位的水然后判断水是否溢出或者到达目标状态,水的高度可以是小数,但是我用整数来处理然后必要时在进行特殊判断。


zju1030.Farmland

http://www.shaidaima.com/source/view/11172

把平面图每个平面提取出来再判断是否简单。遍历每个平面的方法是每次选一条没有遍历过的边(不同方向示为不同)作为新平面的第一条边,然后以这表边反方向后顺时针的下一条边作为第二条边,然后以第二条表边反方向后顺时针的下一条边作为第三条边,以此类推,最后回到第一条边后结束,然后同时求出有符号面积,如果是负的就是外表面,在这里肯定不用考虑,剩下都可能是答案,然后用set的也好,判一下点是否重复就可以判断出是否简单。


zju1041.Transmitters

http://www.shaidaima.com/source/view/11173

比zju1030更简单的平面几何题,容易想到肯定会有一个点落在直径上,所以枚举落在直径上的点,然后就可确定两个不同的半圆,然后再分别暴力枚举一遍看哪些点落在半圆内同时更新答案。


zju1043.Split Windows

http://www.shaidaima.com/source/view/11174

给出的是后缀表达式,直接从左到右扫一次模拟一下边长即可


zju1060.Sorting It All Out

http://www.shaidaima.com/source/view/11175

枚举要判断的表达式数,再用拓补排序来判断表达式组无解,唯一解还是多解。


zju1063.Space Station Shielding

http://www.shaidaima.com/source/view/11176

三维矩形上floodfill看那些面没有被覆盖而且能通过没被占据的方格被外表面所看到……这些面的数目就是答案。


zju1066.Square Ice

http://www.shaidaima.com/source/view/11177

不是0的直接就可以知道方向,0的那些从上到下,从左到右枚举,如果上面没被覆盖,就选择上面放一个'H',否则选择下面,左右同理。


zju1100.Mondriaan's Dream

http://www.shaidaima.com/source/view/11178

典型的状态压缩dp,dp[i][xx...xb](xx...x是一个数,b表示xx...x是二进制,显然x的范围是0,1)表示第i行的覆盖情况,第j个x表示第j列的情况,通常是0表示没被覆盖,相反1表示有。

然后用dfs来求出转移矩阵。即c[xx...xb][yy...yb](yy...yb与xx...xb表达的意思相同)表示能否同xx...xb经过添加一个单位使得变成yy...yb,因此dp[i+1][xx...xb]=sigma{dp[i][yy...yb]*c[yy...yb][xx...xb] | 00...0b<=xx...xb<=11...1b} 时间复杂度是R*(2^C)^2,如果当R很大,C很小的是否可以用矩阵乘法优化到log(R)*(2^C)^3


zju1103.Hike on a Graph

http://www.shaidaima.com/source/view/11179

状态很少,直接bfs


zju1116.A Well-Formed Problem

http://www.shaidaima.com/source/view/11180

比较麻烦的字符串处理,首先划分出tag类,可以封装到一个类里,然后用一个函数判断是否合法……然后用栈来模拟判断整个文本是否合法。感觉数据还是比较厚道,按照他给出的规则判断就可以了……


zju1123.Triangle Encapsulation

http://www.shaidaima.com/source/view/11181

被坑了好几次,要注意好边界的情况,因为总的点也不多,所以细心一点就好。

Program 4 by team X

End of program 4 by team X

这两句话是放在一头一尾的


zju1138.Symbolic Derivation

http://www.shaidaima.com/source/view/11182

每次找出最后一个运算的符号,然后变成两个子问题递归下去然后根据给出的rule合并,括号不能忽略,注意有可能两个符号连在一起要合并成一个符号,如1+-2就换成1-2。


zju1144.Robbery

http://www.shaidaima.com/source/view/11183

bfs得出某一天在某些位置是否有可能,然后如果存在一天只有一处地方则输出。


zju1145.Dreisam Equations

http://www.shaidaima.com/source/view/11184

状态不多,直接搜索所有情况


zju1155.Triangle War

http://www.shaidaima.com/source/view/11186

总的边数就18条,于是可以用dp[w][xx...xb]表示谁做先手,边的选择情况,然后先手得到的最高分……状态转移就有点像模拟这个游戏


zju1185.Metal Cutting

因为那个图形是凸的,显然每一切都会顺着其中的一条边,因为边数/点数很小,于是枚举所有切的顺序,然后每一次可以根据前面来判断这一次需要切多长,最后总和取最小的那一次。


zju1193.Reflections

比较简单的平面几个,直接暴力模拟,光的反射跟镜面反射一样,然后那个镜面就是光线与圆的第一个交点和与那个圆的圆心形成的直线的垂线,而且还要是那个圆的切线那一条。求反射根据角度判断也行,镜面反射原理也行。就是基于反射角等于入射角。


zju1197.Sorting Slides

就是判断一个二分图的其中一些匹配是一定的,方法就是先随便生成一个匹配,然后枚举去掉一条在匹配上的边,如果还是能匹配成功,则说明这个匹配不是固定的,否则就是。重新匹配过后要还原,不然会有问题。


zju1230.Legendary Pokemon
巨烦的一到搜索题,总的状态似乎很多,但是单独一个数据会转移到的情况可能就很少,于是可以用记忆话搜索解决。

认真读清楚游戏的rule,然后那些概率的转移倒不是太难。


zju1237.Fans and Gems

bfs,用RK hash记录状态。


zju1245.Triangles

枚举顶点和高度,要分奇偶……用求和的方式就可以比较快求出连续一片是否全白。


zju1295.Reverse Text
for (cin >> n, getline(cin, text); n; --n) {
getline(cin, text);
reverse(text.begin(), text.end());
cout << text << endl;

}


zju1298.Domino Effect

先用dijkstra求出每个点到1号点的最短路,然后枚举每一个点和每一条边的出最后结束的点和时间,注意在边上的点不一定是中点。


zju1301.The New Villa

http://www.shaidaima.com/source/view/11164

按所在房间号和灯的开关情况编码,然后bfs,相同编码就是相同状态。


zju1321.Parallelepiped Walk

http://www.shaidaima.com/source/view/11166

大体的思路就是把展开正方形成一面,然后就平面两点的距离。展开的方式可以bfs,保持合法就行,譬如说向右展开过就不能向左展开了。

为了方便可以先把一个点固定到一面,然后以那个面为base不动。


zju1387.Decoding Morse Sequences

http://www.shaidaima.com/source/view/11167

把morse转成字符串是多解的,但是把字符串转成morse就是唯一了,所以把答案转成morse,建一个trie图,然后在上面dp……


zju1389.Fill the Cisterns!

http://www.shaidaima.com/source/view/11168

二分答案。


zju1391.Horizontally Visible Segments

http://www.shaidaima.com/source/view/11169

大体思路是线段按x轴排序,按x从小到大枚举相连的第二条和第三条线段,然后求出有多少条可以做第1条线段。

这样做时间复杂度比较大,于是想一个优化的方案,枚举第二条线段的时候暴力染色,然后扫一次y轴就可以知道x轴比第二条线段小的与第二条相连的第一条线段有哪些,用bool数组记录。然后枚举第三条的时候也是扫一次y轴,但是这样还是N^3,但是我们枚举第三条的时候发现因为从x轴小到大枚举,如果以前的枚举覆盖了一定范围,那么后面的线段就可以不枚举这个范围的点,具体做法是用一个next数组记录下一个没被记录的点,动态更新,那么可以证明点的访问数与N是线性相关的。时间复杂度是O(N^2)的,勉强可以过。


zju1413.2D Nim

http://www.shaidaima.com/source/view/11170

如果两个图形相等,就可连一条边,最后的一个二部图,用匈牙利跑一下看是否能完全匹配。

判断两个图形是否相等:固定一个点,通常是最左最上点,然后其他点用相对距离,然后排序,注意旋转的时候最左最上点可能会改变,而且相对距离可要重新排序。然后用这些相对距离判断是否全相等来判断两个图形是否相等。


zju1423.(Your)((Term)((Project)))

外面是'-'而且里面有操作符就把这个括号删掉,注意表达式内有空格


zju1425.Crossed Matchings

首先预处理出一个数组first[i][j], 表示第二层数第i个位置后第一个j出现的位置,然后dp[i][j]表示上一层取到i,下一层取到j的最优解。

那么dp[i][j] ==> dp[i+1][j], //i+1这个点不选;

同时dp[i][j] ==> dp[k][first[first[j][num[k]]][num[i+1]]//i+2<=k<=n,first[j][num[k]]与first[first[j][num[k]][num[i+1]]存在,意思就是相交的两个数分别在第一层i+1和k的位置出现。然后下面一层我们肯定要最出现早最优,因为这样后面才有更多的位置,因此一个就是出现在j后的第一个num[k], 第二个出现在first[first[j][num[k]]][num[i+1]]。


zju1426.Counting Rectangles

枚举矩形的两根竖的线段,扫描一次求出多少条横的线段同时穿过这两条线段,那么任意两天横的都可以和这条竖的组成矩形,所以假如有h条,则答案+=C(h,2);


zju1448.Pattern Matching Using Regular Expression

枚举被匹配字串的开始处,然后dp[i][j]表示到模式的第i个单元,字符串的第j位是否可行,这个dp就比较简单。

然后建议把模式传分成一个个小单元出来,表明好类型,是否带*,(x+可以换成xx*的形式),然后模式串按单元划分而不是按字符,这样应该好做一些。然后我遇到一个比较蛋疼的trick是[c1-c2]中c1和c2是']'。


zju1460.The Partition of a Cake

面数+点数-边数=2,所以求出点数和边数就行,这样个问题都可以归到求两条线段的交点问题,这个问题直接解方程。


zju1462. Team Them Up!

用给出的图求补图就是表示两个点是否要分在不同边,那么如果不是二部图,即存在奇环,无解,否则分成二部图之后dp[i][j], 表示一块含有i个点,一块含有j个点是否有可能。


zju1463.Brackets Sequence

dp[i][j],表示i到j这部分的括号最小要添加的括号数,然后dp[i][j]=min{dp[i][k]+dp[k+1][j] | i<=k


zju1504.Slots of Fun

用了一个觉得很cheat的算法,因为最多只有不超过100的圆,而且圆的位置是固定的,所以先预处理出每一个圆的笛卡尔坐标,接着枚举三个相同字符的圆然后看两两相对距离是否相等。


zju1506.Left labyrinths

这道题一直看不懂,最后问了人才发现走的优先顺序是向左,向后,向右,向前……

求门口的位置,你可以首先从迷宫最左最上的点的左边一点开始走,用一个标记记录里外,一开始为外,按照同样的优先顺序,当走到一个#.#(可以竖着)的时候标记为里,如果再走回这个点就标记为外。然后一个2*2的全是点阵的方格就是courtyard.

最后用方位和方向来做判重做bfs。


zju1509.Family

在一个拓补图上面dp,dp[y][x]=dp[x][y]=(dp[x][pa[y][0]]+dp[x][pa[y][1]])/2, 要求x在拓补序中先于y,然后pa[y][0]和pa[y][1]分别是y的两个parent。

输出略坑,要用到Java的BigDecimal……


zju1509.This Sentence is False

构一个图,用dfs判断一个连通块是否有冲突,并且把一个连通块按对错分成两部分,把大的那一部分加进答案。

你可能感兴趣的:(ACM,其他)