卡常的状压\(DP\),愤怒的小鸟。

其实本来是个很水的状压\(DP\),但因为最后三个点\(n=18\),成功地把我的不可能达到的下界为\(\Omega(2^nn^2)\),紧确的上界为\(O(2^nn^3)\)算法给卡死了\(\rm{OTZ}\)……

那么这个地方,我定义的状态是\(dp_s\)表示猪的状态为\(s\)时的最小鸟个数。那么这个东西转移吧,我想的是枚举每个\(1\)位,把它当做这次更新(杀死)的猪,然后通过其他的猪转移。对于一组猪确定的一个抛物线,再枚举全部的猪,看看能不能从更小的状态更新。

大概枚举两只猪的复杂度都是\(\Theta(n^2)\)左右的,然后\(\Theta(n)\)扫一遍,大概复杂度上界为\(O(n^3)\),但是事实上根本不会到这个地步。对于\(n=15\)的情况还是可以刚一波的。

但是之后就凉凉了,因为它实际只能\(get\)到\(85pts\)。

#include <cstdio>
#include <iostream>
#define MAXN 30
#define MAXM 400000
#define Inf 1926081700using namespace std ; struct Func{ double A, B ;} temp ; int i, j, k ;
int T, t1, t0, dp[MAXM + 1], S0[MAXN], S1[MAXN], N, M ; double X[MAXN], Y[MAXN] ; inline Func chk(int A, int B){double _x1 = X[A], _sx1 = X[A] * X[A] ;double _y1 = Y[A], _sy1 = Y[A] * Y[A] ; double _x2 = X[B], _sx2 = X[B] * X[B] ;double _y2 = Y[B], _sy2 = Y[B] * Y[B] ;return (Func){(_y1 * _x2 - _y2 * _x1)/(_sx1 * _x2 - _sx2 * _x1),  (_y2 * _sx1 - _sx2 * _y1)/(_sx1 * _x2 - _sx2 * _x1)} ;
}
inline bool Calc(Func A, int B){return A.A * X[B] * X[B] + A.B * X[B] == Y[B] ;
}
inline void clear(){ fill (dp, dp + MAXM + 1, Inf) ;}
inline void Init(){t1 = 0, t0 = 0, fill (S1, S1 + N + 1, 0), fill (S0, S0 + N + 1, 0) ;}
int main(){cin >> T ;while (T --){clear() ; dp[0] = 0 ;cin >> N ; M = (1 << N) - 1 ;for (i = 1 ; i <= N; ++ i) scanf("%lf%lf", &X[i], &Y[i]) ;for (i = 1 ; i <= M ; ++ i){Init() ;for (j = 0 ; j < N ; ++ j)if (1 << j & N) S1[++ t1] = j + 1 ;else S0[++ t0] = j + 1 ; for (j = 1 ; j <= t1 ; ++ j)for (k = 1 ; k < j ; ++ k){if ((temp = chk(S1[j], S1[k])).A >= 0) continue ;int S = i ;S ^= (1 << S1[j] - 1), S ^= (1 << S1[k] - 1) ; for (int l = 1 ; l <= t1 ; ++ l){if (l == j || l == k) continue ;if (Calc(temp, S1[l])) S ^= (1 << S1[l] - 1) ;}dp[i] = min(dp[i], dp[S] + 1) ;}               }printf("%d\n", dp[M]) ;}
}

我们思考一个剪枝。

我们的最优解实质上是唯一的,此处的唯一指的是\(DP\)的最优子结构性质。那么我们不妨把转移过程单调起来,而不是让它重复枚举。所以我们要按秩转移,随便从一个开始都行,只要有序、不重复即可。那么不妨从最低位开始。这个东西一开始预处理一遍即可。

于是最终的复杂度就变成了\(\Theta(2^nn)\),十分带劲。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 30
#define t1(i) S1[i][0]
#define min my_min
#define MAXM 400000
#define REG register
#define Inf 1926081700using namespace std ; double X[MAXN], Y[MAXN] ;
const double eps = 1e-7 ; struct Func{ double A, B ;} F[MAXN][MAXN] ;
int m, i, j, k, l, dp[MAXM + 20], Low[MAXM + 20], B[MAXN][MAXN], N, M ;inline bool Calc(Func A, int B){double T = A.A * X[B] * X[B] + A.B * X[B] ; return (T <= Y[B] + eps & T >= Y[B] - eps) ;
}
inline Func chk(int A, int B){double _x1 = X[A], _sx1 = X[A] * X[A], _y1 = Y[A], _sy1 = Y[A] * Y[A] ; double _x2 = X[B], _sx2 = X[B] * X[B], _y2 = Y[B], _sy2 = Y[B] * Y[B], TT = _sx1 * _x2 - _sx2 * _x1 ;return (Func){(_y1 * _x2 - _y2 * _x1) / TT,  (_y2 * _sx1 - _sx2 * _y1) / TT} ;
}
inline int my_min(int A, int B){ return A & ((A - B) >> 31) | B & (~(A - B) >> 31) ;}
int main(){
//  freopen("angrybird.in", "r", stdin) ;
//  freopen("angrybird.out", "w", stdout) ;int T ; cin >> T ; M = (1 << 18) - 1 ; /*for (int i = 1 ; i <= M ; ++ i)for (int j = 0 ; j < 18 ; ++ j)if (1 << j & i) S1[i][++ S1[i][0]] = j + 1 ; */for(i = 0; i <= M ; ++ i){j = 1 ;for ( ; j <= 18 && i & (1 << (j - 1)) ; ++ j) ;Low[i] = j ;}/*for(i=0;i<(1<<18);i++){ //预处理lowunbitint j=1;for(;j<=18 && i&(1<<(j-1));j++);Low[i]=j;}*/while (T --){memset(B, 0, sizeof(B)) ;memset(dp, 127, sizeof(dp)) ;dp[0] = 0 ; cin >> N >> m ; M = (1 << N) - 1 ;for (i = 1 ; i <= M ; ++ i) dp[i] = dp[i - (i & -i)] + 1 ;for (i = 1 ; i <= N ; ++ i) scanf("%lf%lf", &X[i], &Y[i]) ;for (i = 1 ; i <= N ; ++ i)for (j = 1 ; j < i ; ++ j){if (fabs(X[i] - X[j]) <= eps) continue ;F[i][j] = F[j][i] = chk(i, j) ; if (F[i][j].A >= -eps) continue ;for (int k = 1 ; k <= N ; ++ k)if (Calc(F[i][j], k)) B[i][j] = B[j][i] |= (1 << k - 1) ;}for (i = 0 ; i <= M ; ++ i){j = Low[i] ;dp[i | 1 << (j - 1)] = min(dp[i | 1 << (j - 1)], dp[i] + 1) ;for (k = 1 ; k <= N; ++ k) dp[i | B[j][k]] = min(dp[i | B[j][k]], dp[i] + 1) ;}printf("%d\n", dp[M]) ;}
}

转载于:https://www.cnblogs.com/pks-t/p/9937689.html

愤怒的小鸟【$DP$优化】相关推荐

  1. BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]

    4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...

  2. UOJ#7. 【NOI2014】购票 | 线段树 凸包优化DP

    题目链接 UOJ #7 题解 首先这一定是DP!可以写出: \[f[i] = \min_{ancestor\ j} \{f[j] + (d[j] - d[i]) * p[i] + q[i]\}\] 其 ...

  3. [学习笔记]矩阵乘法及其优化dp

    1.定义: $c[i][j]=\sum a[i][k]\times b[k][j]$ 所以矩阵乘法有条件,(n*m)*(m*p)=n*p 即第一个矩阵的列数等于第二个矩阵的行数,否则没有意义. 2.结 ...

  4. [HNOI2008]GT考试[矩阵快速幂+kmp优化的dp]

    解题思路:假如说我们用f[i]表示长度为i的串能组合成无不吉利数字的组合的个数的话我们无法找到f[i]和f[i+1]的关系,就是我们下一位填某个数字会不会出现不吉利串,这就和你前面的串末尾于不吉利串重 ...

  5. 算法笔记--单调队列优化dp

    单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...

  6. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  7. NOI2007 货币兑换 - CDQ分治斜率优化dp

    斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...

  8. bzoj 3120 矩阵优化DP

    我的第一道需要程序建矩阵的矩阵优化DP. 题目可以将不同的p分开处理. 对于p==0 || p==1 直接是0或1 对于p>1,就要DP了.这里以p==3为例: 设dp[i][s1][s2][r ...

  9. POJ 1821 Fence ★(单调队列优化DP)

    题目大意:有一道线性篱笆由N个连续的木板组成.有K个工人,你要叫他们给木板涂色.每个工人有3个参数:L 表示 这个工人可以涂的最大木板数目,S表示这个工人站在哪一块木板,P表示这个工人每涂一个木板可以 ...

  10. HDU-3507Print Article 斜率优化DP

    学习:https://blog.csdn.net/bill_yang_2016/article/details/54667902 HDU-3507 题意:有若干个单词,每个单词有一个费用,连续的单词组 ...

最新文章

  1. linux c sql server 存储过程,SQL Server 2016 - 本机编译的函数
  2. 彻底理解Toast原理和解决小米MIUI系统上没法弹Toast的问题
  3. 2016年云巴产品更新合集
  4. 039_JavaScript对象访问器
  5. java.lang.IllegalStateException: ContainerBase.addChild: start
  6. CF741D-Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths【树上启发式合并】
  7. 通过webbrowser实现js与winform的相互调用
  8. leetcode —— 209. 长度最小的子数组
  9. 你不懂,仅仅有程序猿懂
  10. Windows 平台sqlalchemy 连接oracle数据库
  11. 怎么自学java_菜鸟如何自学Java
  12. Centos7配置AirPrint(解决手机执行多次打印后搜索不到打印机的情况)
  13. 查看linux内存大小
  14. Python中print的用法
  15. Python数学计算工具3、Python 斐波那契数列-前500项列表
  16. kafka安装和部署
  17. 微信小程序图片404时显示默认图片
  18. LaTeX中如何使图片插入紧跟在当前文字之后
  19. oracle 报12560,UNIX系统中Oracle报TNS-12560错误的解决思路
  20. python制作小提琴图

热门文章

  1. Leetcode:Search Insert Position
  2. PostGIS之路——线性参考
  3. 关于Block Formatting Context--BFC和IE的hasLayout
  4. Facebook Auth API文档中没说清楚的事情 (2011-02-28更新)
  5. 《LeetCode力扣练习》第62题 不同路径 Java
  6. Matlab读取二进制文件----fread
  7. 存储过程结果更改编码_Docker安装Minio存储服务器详解
  8. C++知识点11——this指针,const成员函数,访问权限控制
  9. cytoscape使用方法_信号通路分析工具教程——Cytoscape及OmniPath插件
  10. matlab求传递函数在某个频率点的增益_【干货分享】轻松弄懂开关电源TL431环路补偿传递函数推导...