zoukankan      html  css  js  c++  java
  • NOIP2016 愤怒的小鸟

    (f[i]) 表示将$ i $集合中所有小鸟都弄掉用的最少抛物线

    (g[i][j]) 表示在 (i)(j)小鸟(由于(c = 0),两点确定一条抛物线)建立一条抛物线,可以射掉的集合。

    这个(x)可以在未射掉的集合中随便找,因为有可能重复枚举,可以规定(x)为第一个未射掉的集合,这样就可以做到不重不漏了。

    (f[i | g[x][j]] = min{f[i] + 1})

    初始状态: (f[0] = 0),其余为正无穷。

    答案 : (f[(1 << n) - 1])


    二次函数复习(QAQ)

    已知两点((x_1, y_1), (x_2, y_2))在抛物线(y = ax ^ 2 + bx),求(a, b)的值

    先带入:

    (y_1 = ax_1 ^ 2+ bx_1)

    $y_2 = ax_2 ^ 2+ bx_2 $

    暴力一点,先移动过去:

    $ax_1 ^ 2 = bx_1 - y_1 $①

    $ax_2 ^ 2 = bx_2 - y_2 $②

    然后对两个式子分别除以(x_1, x_2),式子就变成了:

    $ax_1 = frac{y_1}{x_1} - b $①

    $ax_2 = frac{y_2}{x_2} - b $②

    然后由② $- $ ①,(b)就被我们消掉了:

    $a(x_2 - x_1) = frac{y_2}{x_2} - frac{y_1}{x_1} $

    然后(a)就出来了:

    (a = (frac{y_2}{x_2} - frac{y_1}{x_1} )/ (x_2 - x_1))

    (b) 就用 ① 带入找就行啦...

    (b = (y_1 - ax_1^2) / x_1)

    不得不说计算机好麻烦(qwq)


    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    using namespace std;
    const int N = 18, M = 1 << N;
    const double eps = 1e-6;
    int n, m;
    double x[N], y[N];
    int f[M], g[N][N];
    bool cmp(double a, double b){
        return fabs(a - b) < eps;
    }
    int main(){
        int T; scanf("%d", &T);
        while(T--){
            memset(f, 0x3f, sizeof f);
            memset(g, 0, sizeof g);
            f[0] = 0;
            scanf("%d%d", &n, &m);
            for(int i = 0; i < n; i++)
                scanf("%lf%lf", x + i, y + i);
            for(int i = 0; i < n; i++){
                g[i][i] = 1 << i;
                for(int j = 0; j < n; j++){
                    if(cmp(x[i], x[j])) continue;
                    double a, b;
                    a = (y[j] / x[j] - y[i] / x[i]) / (x[j] - x[i]);
                    b = (y[i] - a * x[i] * x[i]) / x[i];
                    if(a >= 0) continue;
                    for(int k = 0; k < n; k++){
                        if(cmp(a * x[k] * x[k] + b * x[k], y[k]))
                            g[i][j] |= 1 << k;
                    }
                }
            }
            for(int i = 0; i + 1 < (1 << n); i++){
                int x = 0;
                for(int j = 0; j < n; j++)
                    if(!(i >> j & 1)) { x = j; break; }
                
                for(int j = 0; j < n; j++){
                    f[i | g[x][j]] = min(f[i | g[x][j]], f[i] + 1);
                }
            }
            printf("%d
    ", f[(1 << n) - 1]);
        }
        
        return 0;
    }
    
  • 相关阅读:
    UVA1394 And Then There Was One
    delphi编程CRC算法的实现,以下是全部的代码
    SQLite学习手册(临时文件)
    SQLite学习手册(实例代码<一>)
    SQLite学习手册(锁和并发控制)
    Delphi中比较两个字符串相似性的百分比算法
    SQLite学习手册(内存数据库)
    delphi 读取网卡mac的3种方式
    从内存中加载并运行exe
    Windows消息机制要点
  • 原文地址:https://www.cnblogs.com/dmoransky/p/11391722.html
Copyright © 2011-2022 走看看