UOJ 265 NOIP 2016 DAY2 T3 浅谈预处理状态压缩动态规划

来源:互联网 发布:网易云音乐wifi无网络 编辑:程序博客网 时间:2024/05/17 00:06

这里写图片描述
世界真的很大
要是当年我会一点状压该多好。。
虽然现在我状压也很差,但是还是把这道题水出来了
马上要NOIP2017了,抓紧调整状态才好

看题先:

description

Kiana 最近沉迷于一款神奇的游戏无法自拔。简单来说,这款游戏是在一个平面上进行的。有一架弹弓位于 (0,0)(0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如 y=ax2+bxy=ax2+bx 的曲线,其中 a,ba,b 是 Kiana 指定的参数,且必须满足 a<0a<0a,ba,b 都是实数。当小鸟落回地面(即 xx 轴)时,它就会瞬间消失。在游戏的某个关卡里,平面的第一象限中有 nn 只绿色的小猪,其中第 ii 只小猪所在的坐标为 (xi,yi)(xi,yi)。如果某只小鸟的飞行轨迹经过了 (xi,yi)(xi,yi),那么第 ii 只小猪就会被消灭掉,同时小鸟将会沿着原先的轨迹继续飞行;如果一只小鸟的飞行轨迹没有经过 (xi,yi)(xi,yi),那么这只小鸟飞行的全过程就不会对第 ii 只小猪产生任何影响。例如,若两只小猪分别位于 (1,3)(1,3) 和 (3,3)(3,3),Kiana 可以选择发射一只飞行轨迹为 y=−x2+4xy=−x2+4x 的小鸟,这样两只小猪就会被这只小鸟一起消灭。而这个游戏的目的,就是通过发射小鸟消灭所有的小猪。这款神奇游戏的每个关卡对 Kiana 来说都很难,所以 Kiana 还输入了一些神秘的指令,使得自己能更轻松地完成这个游戏。这些指令将在【输入格式】中详述。假设这款游戏一共有 TT 个关卡,现在 Kiana 想知道,对于每一个关卡,至少需要发射多少只小鸟才能消灭所有的小猪。由于她不会算,所以希望由你告诉她。

input

从标准输入读入数据。第一行包含一个正整数 TT,表示游戏的关卡总数。下面依次输入这 TT 个关卡的信息。每个关卡第一行包含两个非负整数 n,mn,m,分别表示该关卡中的小猪数量和 Kiana 输入的神秘指令类型。接下来的 nn 行中,第 ii 行包含两个正实数 xi,yixi,yi,表示第 ii 只小猪坐标为 (xi,yi)(xi,yi)。数据保证同一个关卡中不存在两只坐标完全相同的小猪。如果 m=0m=0,表示 Kiana 输入了一个没有任何作用的指令。如果 m=1m=1,则这个关卡将会满足:至多用n/3+1⌉⌈n/3+1⌉ 只小鸟即可消灭所有小猪。如果 m=2m=2,则这个关卡将会满足:一定存在一种最优解,其中有一只小鸟消灭了至少n/3⌋⌊n/3⌋ 只小猪。保证 1n181n180m20m20<xi,yi<100<xi,yi<10,输入中的实数均保留到小数点后两位。上文中,符号 ⌈c⌉⌈c⌉ 和 ⌊c⌋⌊c⌋ 分别表示对 cc 向上取整和向下取整,例如:⌈2.1⌉=⌈2.9⌉=⌈3.0⌉=⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3⌈2.1⌉=⌈2.9⌉=⌈3.0⌉=⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3。

output

输出到标准输出。对每个关卡依次输出一行答案。输出的每一行包含一个正整数,表示相应的关卡中,消灭所有小猪最少需要的小鸟数量。

状压DP有一个特点就是其数据范围奇小无比
看一下数据范围,n < 18,嗯,状压

考虑有无数条抛物线,但是大多数是没有用的,比如只打一头猪或者打不到猪的抛物线。因为3点确定一条抛物线,原点给出,那么一条抛物线至少可以打两只猪。

考虑状压Dp,我们需要状压的自然是n,也就是猪的状态,而且每只猪只能是0或1,两种状态。很自然想到是打得中,打不中。那么整个01串表示的就是打中了哪些猪。
什么东西能用打中哪些猪来表示呢,自然就是抛物线了

所以我们考虑得到所有的抛物线来转移状态,就可以用枚举两个点的方法来找到所有的抛物线。

但是这样有个漏洞,就是有可能一条抛物线是开口向上的,就不符合题意,就不能选
以防万一,我们再加入所有只能打一只猪的抛物线,尽管至少可以打两只猪,但是抛物线可以交叉,所以没有关系

那么考虑状压DP的转移,一般有填表法和刷表法两种
填表法适用于有多种状态向当前状态转移,即找前驱状态
刷表法适用与当前状态可以去更新多种状态,即找后继状态
而考虑这道题,假设i表示当前状态,只能通过预处理出的抛物线来转移,而一只猪的位置可以重复计算,就是说i的某只猪如果被打了不一定只能从这只猪没被打的状态转移过来,所以无法找前驱状态,只能去更新后继状态,也就是所谓的刷表法

完整代码:

#include<stdio.h>#include<cmath>#include<algorithm>#include<cstring>using namespace std;const double eps=1e-10;const int INF=0x3f3f3f3f;struct PIG{    double x,y;}pig[100010];int n,T,m,ste,tot=0,f[2000010];int lne[1000010];void init(){    memset(lne,0,sizeof(lne));    ste=(1<<n)-1;    tot=0;}int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        init();        for(int i=1;i<=n;i++)            scanf("%lf%lf",&pig[i].x,&pig[i].y);        for(int i=1;i<n;i++)        {            double x1=pig[i].x,y1=pig[i].y;            for(int j=i+1;j<=n;j++)            {                double x2=pig[j].x,y2=pig[j].y;                double a=(y1*x2/x1-y2)/(x1*x2-x2*x2);                double b=(y1-a*x1*x1)/x1;                if(a>-eps) continue ;                tot++;                for(int k=1;k<=n;k++)                {                    double xk=pig[k].x,yk=pig[k].y;                    if(fabs(a*xk*xk+b*xk-yk)<eps)                        lne[tot]+=(1<<k-1);                }            }        }        for(int i=1;i<=n;i++)            lne[++tot]+=(1<<i-1);        memset(f,INF,sizeof(f));        f[0]=0;        for(int i=0;i<=ste;i++)            for(int j=1;j<=tot;j++)                f[i | lne[j]]=min(f[i | lne[j]],f[i]+1);        printf("%d\n",f[ste]);    }    return 0;}/*EL PSY CONGROO*/

嗯,就是这样

原创粉丝点击