yijan
2018-08-14 22:58:36
这是一篇 2018.8.14 提交的blog,现在是 2020.2.7 并且貌似快要上luogu日报了。。
我的另外一篇日报文
upd(2020.6.3) 感谢 @Thomasguo666 @nao_nao 指出错误。。如果还有写错的地方在评论区回复一下就好了/kk
从dp的条件说起,事实上dp真正需要的条件只有三个:
学过dp都知道,状态转移方程是最难的。但是这里我们要从状态说起。
状态是一个非常玄学的东西。多数时候数组存储就可以,但有时状态数量太多,就把一个数组压缩成一个数字,通过位运算进行操作。
当然这种压缩往往只是选或者不选两种状态,状态太多了无法使用这种策略。
还是先从位运算说起。
计算机存储数据采用补码二进制,你现在使用的每个int(longlong)在计算机都是一串二进制码。int的大小范围是
后面这些运算在计算器的程序员模式都有(或直接把c++当计算器),可以自行验证
与普通的&&区别?这个是按位与!每一位都要进行!如果同为1则为1,不同为1则为0。比如,
与运算有什么用?可以判断某一位是否为1。
比如判断k的从右数第j位是否为1 就是
if(k&(1<<j))
&一般被看作集合的交集。比如,第k位是1代表这个集合有k这个元素,第k位是0表示这个集合没有k这个元素。则一个整数就是一个集合,两个集合的交就是这两个数字并起来。这点非常有用,一定记住!
很容易证明,与运算是不升的,也就是说,一个数字不管怎么与,也不可能大于原数字。这一点有些题可以用到(对于unsigned)。
记得前段时间打cf做了一个题就是关于与运算,可以看一下:
CF1013B
这个运算一般用来给集合赋值。比如把k的二进制从右第j个改成1(不管是不是1都改)就是:
k |= (1<<j);
其次,或运算经常被用于作为集合的并集。假设a,b是两个集合,那么他们的并就是a|b。这和与运算相反,也是一个非常重要的特性。
同时,或运算是不降的。也就是说,不管怎么或,也不可能产生的数字比原来数字还小(对于unsigned)。
异或运算与前面的不同了,异或运算被称为不进位加法。
两个数字对于每一位,相同为0,不同为1.
比如
是不是很像不进位的加法?
异或最为重要的性质是x^y^y=x
也就是说它的逆运算为本身!
这个运算用途比较玄学,需要用心感悟
左移操作 <<
把二进制所有位向左边移一位,最低位补0,最高位移出去(消失)。多数时候跟*2等价,但是一定注意int不要移到31,这时候就会移到符号位,如果符号位为1,就变成负,符号位0,正。如果不想考虑这么麻烦,使用unsigned可以解决问题。
尝试一下输出1<<31,发现输出了-2147483648?!为什么?因为计算机存储使用补码。对于负数,补码是会与源码发生改变。不知道的自行百度,在此不再累赘。
右移操作 >>
右移操作自然就是把所有位向右移动。超出右边的会自动去掉。但是区别在于,它左边不是补0,而是补符号位。(对于unsigned不存在)。比如符号位是1,那么右移后左边补充的是1,而不是0. 这个可以当作除以二用。
这个用得非常少,就是把二进制所有位全部取反。
比如~0 =
也就是说,~a=-a-1
这是个非常玄学的东西,实在想要搞清楚自行百度,这里不再赘述。强烈建议大家全部打上括号!!预防万一突然记错/打错。这种例子数不胜数。
另外,为了避免玄学错误,请尽量用unsigned代替int进行位运算。
给你n个城市和城市之间的通路的长度,找出一条经过所有城市一次且仅经过一次的路线,使得这条路线的长度最短。
因为设计路线,所以状态肯定与你现在所在的城市有关系。其次,你还需要保存经过了哪些城市(不能重复走)。如果一个城市被经过了用1表示,没有到过用0表示一个整数就可以表示所有城市是否被走过,那么可以得到
洛谷 P2704====传送门====
此题暴力肯定超时,怎么办呢?
因为m<=10,所以每一行的状态肯定可以表示成一个整数。还是假设放置是1,不放是0.
然后我们可以枚举一行中的所有的状态(可以打表啦),而且手推一下会发现一行状态数量是很少的。(不会超过100)
于是我们记录了所有状态的士兵数量。根据题意我们明显发现,每一行只与其前两行有关系。因此我们假设
其中j是枚举的i-2行状态,sum代表这种状态下的数量。
下面就是状态是否可行的问题了。首先,第i行的状态肯定不可以和环境冲突啊!
第i行如果和环境冲突,那么肯定在有山的地方放了1。怎样判断比较快?输入的时候就转化成二进制。如果有山这位就是1,若果没有就是0.这个时候,如果原地形是0,则第i行状态可以是1/0,如果原来是1,则第i行必须是0.这不就是按位与运算吗?如果原地形和第i行的状态and一下后不是0,那么自然代表状态不成立(出现了两个1!)所以这里判断只需要一次与运算。
然后判断当前行和上面一行冲突是否。这里我们发现和判读地形一样,不能同为1,所以也是一遍与运算。
判断当前行与上上行,仍然是一遍与运算。
最后捋一遍思路
近年来noip中dp考得越来越多(每年基本都有)
难度也不断上升。
作为一个dp蒟蒻 感觉dp题还是得靠多做,找感觉。
最后祝愿大家(包括我)noip2018 rp+=66666
最后宣传一下blog。
yijan.co