一些题目总结

来源:互联网 发布:热血江湖sf源码 编辑:程序博客网 时间:2024/06/05 11:35

poj2392 poj1742

两个问题都是多重背包问题。即给定每件物品的确定的件数,求可以得到的最大价值。
这类问题有两种解决方法。一种是把件数c分解成若干个件数的集合,然后我们可以用这些集合里的件数来组成1..c的任何状态,我们比较自然地能想到把它们分解用二进制分解。如7(111)就可以用110,11,1来表示。所以把每一个重复的件数进行一个log2的转化,就成了一个01背包。第二种解决方法是类似完全背包的写法,只要加上一个use[]数组,来统计f[j]状态时用了多少个第i种,然后我们f[j] |= (f[j-size[i]])时加上use[j-size[i]]+1<=c[i] (c[i]为第i种的件数)就好了。
2392还有一个小的贪心,就是我们要先选择搭矮的电梯,这样才能让总高度要更高。

poj2773

简单容斥原理。
题意是给出n和k求出第k个与n互素的数。
我们可以反求出从1..n中有多少与n不互素的数,再用二分逼出k。
如何求出从1..n中有多少与n不互素的数呢?我们可以先把n的所有素因子求出来。比如说12的素因子有2,3,然后1..12中2的倍数就有12/2个,这些数与12不互素,对3同理,这样就有多算出6的倍数,减去即可。啰嗦的说了一下容斥原理。用dfs比较轻松地就能实现。

poj1664

递归+记忆化搜索
递归。然后为了减少重复计算,存储下已经算出的状态。类似的有poj1088的记忆化搜索。递归部分虽然不很复杂,但需要锻炼。

poj1185

状态压缩DP

题目大意
n*m的地图,由’H’或P组成。’P’则可以在上面放炮弹,炮弹可以攻击到上下左右各两个方格的位置。在防止误伤的情况下,求最大放置的炮弹数。

这种问题,一个很重要的处理(优化)在于首先用dfs把每一行的可行状态给先给预处理出来,并且计算出这个状态的1的个数防止后面重复计算。对于第i行,我们把所有的状态放在s[i][j]中。
每一行的状态受到前两行的状态的影响。f[i][j][k]表示第i行为状态s[i][j],第(i-1)行状态为s[i-1][k]的最大导弹数。 f[ i ] [ s ] [ t ] = max ( f [ i ] [ s ] [ t ] , f [ i - 1 ] [ t ] [ k ] + count ( a[i][j] ) )。最后,第一维可以滚动。

poj2482

扫描线+离散化+线段树

题目描述是一段冗长的情书。题意不复杂,在一个平面内有N个星星,每个星星都在一个亮度值,用一个W*H的矩形去围这些星星,(边上的不算) 求能得到的最大亮度值。

本题和poj1981类似,每个星星的影响范围落在(x,y)->(x+w-1,y+h-1)里,有权值val。所以我们可以用一条平行于y方向的线去扫描过去,到x的时候就把y方向上的(y,y+h-1)加上val,到x+w-1的时候再把这个干掉(相当于加上(-val)即可)。由于星星不多而方格较大,需要对y方向进行离散化。在y方向上的线段树的结点存放的是这个纵坐标被离散化后的代表数。STL的unique在离散化的时候好用。

分成两段来匹配

题意是有一个n长的字符串和m个猜测,接下去有m行,每行有两个输入,一个是n长的字符串,一个是整数s,表示某一轮猜测的字符串以及与原n长字符串相比正确的位数,问存在多少个n长的字符串,使得所有猜测成立。(n<=35,m<=10)

n<=35,所以不能直接暴力,但是这个题目给了另外一个比较水的条件,就是每个s<=5,所以一个方法是可以直接枚举和第一个匹配的字符串,共有35C6种可能,不会超时。此外,也可以分成两段来算,先穷举出前n/2的所有可能,计算出其和m个字符串的匹配数,放到vector里,然后再放到一个map里面,val的值+1。枚举后一半,每个vector存的值是s[i]-匹配数,最后结构加上map里的这个vector的值就可以了。时间复杂度大概是o(n*m*2^(n/2))。//感觉和平方分割那种思想有些类似的意思

一些注意点

  • 注意一下实数类型的输出,%f,%lf,以及强制转化时的括号等等之类的(poj的g++与c++提交有时会一个WA一个AC,所以实在找不到错误就换个方式交一下)

  • 初始化!头脑不清醒的时候还是建议开全局变量,毕竟初始值为0可能会逃过一些问题。另外局部变量能开的大小也比全局要小。

  • 边界问题,在提交前注意一些比较小但比较特殊的情形,可能事半功倍。

  • 有一些题目的数据可能会多一些空行空格之类的,用cin>>ch是个不错的选择。

0 0