卡常的状压\(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 1926081700 using 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 1926081700 using 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++){ //预处理lowunbit
int 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]) ;
}
}

愤怒的小鸟【$DP$优化】的更多相关文章

  1. BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4026  Solved: 1473[Submit] ...

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

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

  3. bzoj 1010 斜率优化DP

    我的第二道斜率DP. 收获: 1.假设两个位置:p<q<i,然后让某一位置优,看其满足什么性质,所谓斜率优化就是满足: (g[q]-g[p])/(f[q]-f[p])  op h[i] 要 ...

  4. [HDU2829] Lawrence [四边形不等式优化dp]

    题面: 传送门 思路: 依然是一道很明显的区间dp 我们设$dp\left[i\right]\left[j\right]$表示前$j$个节点分成了$i$块的最小花费,$w\left[i\right]\ ...

  5. HDU2829 Lawrence —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-2829 Lawrence Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  6. HDU3480 Division —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3480 Division Time Limit: 10000/5000 MS (Java/Others)    Memory ...

  7. HDU3045 Picnic Cows —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3045 Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memor ...

  8. HDU1300 Pearls —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-1300 Pearls Time Limit: 2000/1000 MS (Java/Others)    Memory Lim ...

  9. HDU3507 Print Article —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3507 Print Article Time Limit: 9000/3000 MS (Java/Others)    Mem ...

  10. BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Statu ...

随机推荐

  1. 在AE二次开发中出“正试图在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。”异常解决方案

    今天的一个项目总用到了AE的开发组件,也就是ESRI公司提供的一系列的开发包(组件)都是以dll(动态链接库的形式)然后今天在调试的时候却出现了“正试图在 OS 加载程序锁内执行托管代码.不要尝试在 ...

  2. AGC009:Eternal Average

    传送门 好神啊 直接考虑一棵 \(n+m\) 个叶子的 \(k\) 叉树,根结点权值为 \(\sum_{i\in m}(\frac{1}{k})^{deep_i}\) 对于一个 \(deep\) 的序 ...

  3. 根据多个点使用canvas贝赛尔曲线画一条平滑的曲线

    众所周知想用canvas画一条曲线我们可以使用这些函数: 二次曲线:quadraticCurveTo(cp1x, cp1y, x, y) 贝塞尔曲线:bezierCurveTo(cp1x, cp1y, ...

  4. 献给java求职路上的你们

    为了更好的树立知识体系,我附加了相关的思维导图,分为pdf版和mindnote版.比如java相关的导图如下: 由于时间仓促,有些地方未写完,后面会继续补充.如有不妥之处,欢迎及时与我沟通. 相关概念 ...

  5. Solr常用操作命令

    1. 新建collection ./solr create_collection -c collection_vip -d /opt/lucidworks-hdpsearch/solr/server/ ...

  6. Android属性动画:插值器与估值器

    声明:本篇文章部分内容来自<Android开发艺术探索>. 我们都知道对于属性动画可以对某个属性做动画,而 插值器(TimeInterpolator)和 估值器(TypeEvaluator ...

  7. Django 模板语言 标签

    前言:django的模板语法基本和flask的jinja2基本一样.下面比较一下两个模板语法的区别. ------深度变量的查找(万能的句点号) 在 Django 模板中遍历复杂数据结构的关键是句点字 ...

  8. python中的字符串编码问题——3.各操作系统下的不同编码方式

    各操作系统下的不同编码方式  先看一下 linux,python2.7 >>> B = b'\xc3\x84\xc3\xa8' >>> B.decode('utf- ...

  9. 《SQL Server 2008从入门到精通》20180627

    数据库范式理论 范式理论是为了建立冗余较小结构合理的数据库所遵循的规则.关系数据库中的关系必须满足不同的范式.目前关系数据库有六种范式:第一范式(1NF).第二范式(2NF).第三范式(3NF).BC ...

  10. Winform 多个窗口编辑同一条数据同步的实现

    场景: 一个主窗口中,可以在列表(DataGridView)里选中一条记录编辑,打开一个编辑窗口(非模态窗口),编辑窗口保存后需要刷新父窗口,由于编辑窗口是非模态窗口,如果打开了多个窗口,并且都是编辑 ...