【题解】NOIP2016愤怒的小鸟

一眼n<=18状压dp……方程什么的都很显然,枚举两只小鸟,再将这条抛物线上的小鸟抓出来就好啦。只是这样O(n^3)的dp必然是要TLE的,我一开始这样交上去显然跑得巨慢无比,后来转念一想:面对一个崭新的情况的时候,只有搭配的优劣之分,没有先后的区别,所以最外面的一层可以直接去掉,变成O(n^2)的dp。这样就跑的很快啦~

PS:print()函数只是调试输出,作用是输出now 的二进制形式+dp[now];

#include <bits/stdc++.h>
using namespace std;
#define db double
#define eps 0.00000001
#define maxn 30
#define maxm (1 << 18) + 20
#define INF 999999
int T, n, m, dp[maxm], len;
db a, b, x[maxn], y[maxn];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

void Get_ab(db x1, db y1, db x2, db y2)
{
    a = (y1 * x2 - y2 * x1) / (x1 * x1 * x2 - x2 * x2 * x1);
    b = (x2 * x2 * y1 - x1 * x1 * y2) / (x1 * x2 * x2 - x1 * x1 * x2);
}

bool On_Line(db x1, db y1)
{
    db r = x1 * x1 * a + x1 * b;
    if((r - y1 < eps) && (r - y1 > -eps)) return true;
    else return false;
}

void print(int now)
{
    int a[30], tot = 0;
    int k = now;
    while(k)
    {
        a[++ tot] = k & 1;
        k >>= 1;
    }
    cout << now << " ";
    for(int i = 1; i <= tot; i ++) cout << a[i];
    for(int i = n; i > tot; i --) cout <<‘0‘;
    cout << " " << dp[now];
    cout << endl;
}

void DP(int now)
{
    if(dp[now] != INF) return;
    for(int i = 0; i < n; i ++)
    {
        if(((1 << i) & now)) continue;
        for(int j = i + 1; j < n; j ++)
        {
            if(x[i] == x[j]) continue;
            Get_ab(x[i], y[i], x[j], y[j]);
            if(a >= 0) continue;
            int aft = 0;
            for(int k = 0; k < n; k ++)
                if(On_Line(x[k], y[k])) aft = (aft | (1 << k));
            int tem = aft | now;
            DP(tem);
            dp[now] = min(dp[now], dp[tem] + 1);
        }
        int aft = (1 << i);
        int tem = aft | now;
        DP(tem);
        dp[now] = min(dp[now], dp[tem] + 1);
        break;
    }
}

void init()
{
    len = (1 << n) - 1;
    for(int i = 0; i < len; i ++) dp[i] = INF;
}

int main()
{
    T = read();
    while(T --)
    {
        n = read(), m = read();
        init();
        for(int i = 0; i < n; i ++)
            scanf("%lf%lf", &x[i], &y[i]);
        dp[len] = 0;
        DP(0);
        printf("%d\n", dp[0]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/twilight-sx/p/8460558.html

时间: 2024-08-25 11:06:05

【题解】NOIP2016愤怒的小鸟的相关文章

[NOIP2016]愤怒的小鸟 D2 T3 状压DP

[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如y=ax2+bx的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行

[题解]noip2016普及组题解和心得

[前言] 感觉稍微有些滑稽吧,毕竟每次练的题都是提高组难度的,结果最后的主要任务是普及组抱一个一等奖回来.至于我的分数嘛..还是在你看完题解后写在[后记]里面.废话不多说,开始题解. 第一题可以说的内容不是很多吧.直接暴力,计算每种铅笔需要花费的金额. 只不过计算的时候,需要注意如下问题 如果不是整数倍,除完后要加1 神奇的Linux系统,很多人的第三个点wa了,所以要养成良好的编写代码的习惯 Code(我的源程序) 1 #include<iostream> 2 #include<fst

noip2016 愤怒的小鸟

题目描述 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会被消灭掉,同时小鸟将会沿着原先

[NOIP2016]愤怒的小鸟 D2 T3

Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如y=ax2+bx的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会

9.22考试 crf的军训 题解

做这道题时由于第一道题太水了,第一反应是NOIP T2级别的题,需要拿上70~100的分,然后就开始分析,当然最后事实证明我错了-- 这道题当时首先联想到了 NOIP2016愤怒的小鸟 当然,数据范围不允许,但是我当时只是为了先拿到小数据的分数,所以先没考虑数据范围,在这里简单提一下:首先我先枚举了每一个状态,然后判断这个状态中的书是否能连在一起,然后就是一个2^(2*n)的转移,好吧,我承认,不是正宗的愤怒的小鸟打法,是当时集中生智编出来的,但是对于n<=10的复杂度还是够用的. 然后对于小于

noip模拟赛 星空

分析:非常神的一道题.迭代加深搜索+rand可以骗得20分.状压n的话只有24分,必须对问题进行一个转化. 在爆搜的过程中,可以利用差分来快速地对一个区间进行修改,把一般的差分改成异或型的差分: b[i] = a[i] ^ a[i + 1],每次翻转操作实际上就是在b[l-1]取反,b[r]上取反.那么先对原序列建一个差分数组,实际上的操作就是在对这个差分数组进行操作:每次可以选两个数取反,问多少次能够把这个数组中的所有元素全部变成1.这是一个很神奇的转化. 每次取反的两个数长度都是固定的.两种

简单算法复习

个人认为,信息学竞赛中最难的部分,要数算法的学习和灵活运用了吧.其实算法呢,讲讲概念很好理解,可一道题目中,就千变万化,纯看个人造诣了.本人在这方面比较弱...讲的太浅显,或者有什么问题还请不吝赐教. 1.搜索 好的搜索是一门艺术,是优雅的暴力. 这几天的的模拟赛告诉我一个真理:练好搜索!练好搜索!!练好搜索!!!毕竟我们实力有限是吧.所以说正解不强求,但暴力分怎么也得拿一点啊. 无奈基础太差,优化算法涉猎较少,现在摆出这几天刷的题吧. 求先序排列:大水题(PJ),但是让我对树的先序,中序,后续

DAY 3 上午

状压DP 状态压缩dp 状态压缩是设计dp状态的一种方式. 当普通的dp状态维数很多(或者说维数与输入数据有关),但每一维总量很少时,可以将多维状态压缩为一维来记录. 这种题目最明显的特征就是:都存在某一给定信息的范围非常小(在20以内),而我们在dp中所谓压缩的就是这一信息. (或者是在做题过程中分析出了某一信息种类数很少) 我们来看个例子. 经典题 ?给出一个n*m的棋盘,要放上一些棋子,要求不能有任意两个棋子相邻.求方案数. ? n<=100; ?m<=8. 如果m固定的话可以设f[i]

DP&amp;图论 DAY 3 上午

DP&图论  DAY 3  上午 状态压缩dp >状态压缩dp ?状态压缩是设计dp状态的一种方式.?当普通的dp状态维数很多(或者说维数与输入数据有关),但每一维总量很少是,可以将多维状态压缩为一维来记录.?这种题目最明显的特征就是: 都存在某一给定信息的范围非常小(在20以内),而我们在dp中所谓压缩的就是这一信息.?(或者是在做题过程中分析出了某一信息种类数很少)?我们来看个例子. >经典题?给出一个n*m的棋盘,要放上一些棋子,要求不能有任意两个棋子相邻.求方案数.? n<