ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AcWing 524. 愤怒的小鸟

2022-01-04 14:32:26  阅读:210  来源: 互联网

标签:小鸟 小猪 int pig 524 ++ 抛物线 path AcWing


题目传送门

#include <bits/stdc++.h>
//https://www.acwing.com/solution/content/16261/
using namespace std;
const int N = 20;        //小猪的数量上限
const int M = 1 << N;    //小猪在某个时刻的击中状态,比如0011,两个没有被击中,两个被击中
const double eps = 1e-8; //用于判断双精度差值误差的常数
//结构体,用于描述小猪的位置
struct Node {
    double x, y;
} pig[N];

int path[N][N];   //表示第i个点和第j个点构成的抛物线能覆盖的点的状态
int f[M];         //f[i] 表示当前击沉状态i表示的小猪所需要的最少的小鸟数量
int n;            //n只小猪
int m;            //Kiana 输入的神秘指令类型,最后此变量没有用到

//浮点数比较
bool cmp(double a, double b) {
    if (fabs(a - b) < eps) return true;  // a == b
    return false;
}

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    int T;      //T组数据
    cin >> T;
    while (T--) {
        cin >> n >> m;
        for (int i = 0; i < n; i++) cin >> pig[i].x >> pig[i].y;
        //多组数据,每次清空
        memset(path, 0, sizeof path);
        for (int i = 0; i < n; i++) {
            //(i,i)点肯定能覆盖掉自己
            path[i][i] = 1 << i;
            for (int j = 0; j < n; j++) {
                double x1 = pig[i].x, x2 = pig[j].x;
                double y1 = pig[i].y, y2 = pig[j].y;
                //计算抛物线y = a(x^2) + bx
                if (cmp(x1, x2)) continue;  //横坐标一样的话,是不能构成抛物线的
                //推导的公式
                double a = (y1 / x1 - y2 / x2) / (x1 - x2);
                double b = (y1 / x1 - a * x1);
                //此题抛物线需开口向下
                //注意浮点数不能用等于
                if (a > 0 || cmp(a, 0.0)) continue;

                //计算path[i][j]的能覆盖的点的状态
                //参数a,b的抛物线已生成,重新遍历每只小猪,看看这只小猪是不是在这个抛物线上
                for (int k = 0; k < n; k++) {
                    double x = pig[k].x, y = pig[k].y;
                    if (cmp(a * x * x + b * x, y))//此小猪是不是符合此抛物线方程
                        path[i][j] += 1 << k; //记录由i,j两个点可以确定的抛物线方程包含k这只小猪
                }
            }
        }
        //清空DP数组
        memset(f, 0x3f, sizeof f);
        f[0] = 0;//啥也不覆盖,抛物线个数是0
        for (int i = 0; i < 1 << n; i++) {  //遍历所有状态
            int x;//下一个要准备被击沉的小猪x
            for (int j = 0; j < n; j++) {   //遍历每个小猪
                //找到状态i中没覆盖的猪的标号,从小到大,找到一个就行
                if ((i >> j & 1) == 0) {
                    x = j;
                    break;
                }
            }
            //找到i状态下没有被消灭的小猪的编号x,
            //枚举可消灭它的抛物线path[x][j]并更新状态:
            for (int j = 0; j < n; j++)//枚举每只小猪,拼出x,j两只小猪,就能枚举出所有可以击沉X的抛物线
                f[i | path[x][j]] = min(f[i | path[x][j]], f[i] + 1);
        }
        //输出结果
        cout << f[(1 << n) - 1] << endl;
    }
    return 0;
}

标签:小鸟,小猪,int,pig,524,++,抛物线,path,AcWing
来源: https://www.cnblogs.com/littlehb/p/15762338.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有