思路
做的第一道状压dp题。状压dp通常是用来解一些NP完全(没有多项式时间算法)的问题。当然,这种题的范围一般比较小。状压dp的思路就是使用2进制保存状态(这也是为什么范围比较小的原因之一),比如旅行商问题,我们用数位上的1代表以访问过的点,0则是未访问过。通常状压dp的格式是1
2
3
4
5
6
7for(int i=0;i<(1<<n)-1;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
//dp的转移方程
}
}
}
大部分的时间复杂度为O(n^2log(n))。
一开始想写个O((n^2)(2^n))的,结果似乎会TLE,题目要求的复杂度是O((2^n)n)。对于这道题我们能够发现,选取的顺序其实是无关的。所以我们强制要求顺序取,也就是i之前的物品必须都取了,这个思路最终表现在剪枝上,我们对1-(1<<n-1)的每个数都只在最低0位上进行或1的操作。我们很显然发现每个点都取一次,那么显然时间复杂度为O((2^n)n).
代码
1 |
|